# HideFile 安全性：加密怎么做的，又在哪里止步

HideFile 在浏览器里，用由你的密码生成的密钥加密文件，再把加密后的结果存放在一张普通的照片、PDF 或视频里。你的文件和密码都不会发送给我们。本页写明了所用的算法和参数，列出应用到底会发送什么，并坦率说明它的局限，包括细心的读者会拿来质疑我们的那些。

记住两个概念，后面就不会混。加密是安全层：没有密码，内容无法读取。封面文件是伪装：它改变的是加密后的字节在别人浏览你的文件时的样子，并不会让它们对正在检查的人变得不可见。

## 你的密码在你的设备上变成密钥

创建上锁文件时，HideFile 用 **Argon2id**（1.3 版）把你的密码变成密钥。这是一种内存困难型（memory-hard）的密钥派生函数。内存困难的意思是，每次尝试除了花时间，还要占用一块内存，所以即使用专门为猜密码打造的硬件，猜测也依然很慢。

成本取决于文件是在哪里创建的。在桌面浏览器中，Argon2id 使用 64 MiB 内存、3 次迭代、单线程通道。如果浏览器报告自己是手机或平板，或内存不超过 4 GB，则使用 19 MiB、2 次迭代、单线程通道，因为手机浏览器无法稳定地在每次解锁时占用 64 MiB 而不出错。这个较低的设置符合 OWASP 对 Argon2id 的最低推荐。这些参数存放在上锁文件内部，所以在桌面上创建的文件，在手机上打开时仍保持 64 MiB 的成本。

每个上锁文件都有一个随机的 16 字节盐值，和文件存放在一起。两个人选了同样的密码，最终得到的密钥也不同，所以没有人能预先算好一张猜测表，拿去对付所有文件。

## 你的文件用 XChaCha20-Poly1305 封存

由密码生成的密钥并不直接加密你的文件。每个上锁文件都有自己的随机 256 位文件密钥，在你的设备上生成。密码密钥负责包裹这个文件密钥，文件密钥负责封存你的文件。

封存使用 **XChaCha20-Poly1305**，这是一种带认证的密码算法：既保证内容私密，也能发现篡改。文件以记录的形式存放，每条记录都有自己的随机 192 位 nonce 和一个 Poly1305 认证标签。如果某条记录被改动，不论是副本损坏还是有人故意改的，解锁都会报错失败，而不是悄悄返回错误的内容。

<figure><img src="/docs/guides/img/product/security-encryption-flow.svg" alt="浏览器内部：密码和随机的 16 字节盐值进入 Argon2id（64 MiB 和 3 轮，手机和低内存浏览器为 19 MiB 和 2 轮），生成 32 字节的密码密钥。这个密钥包裹一个随机的 256 位文件密钥。XChaCha20-Poly1305 把文件封存成记录，每条记录带随机的 192 位 nonce 和防篡改标签。封存后的记录存放在封面文件内部。" loading="lazy" width="100%"><figcaption>一个密码，两把密钥。密码密钥只负责包裹文件密钥。</figcaption></figure>

这两种算法都来自开源的 RustCrypto 库（argon2 和 chacha20poly1305 这两个 crate）。我们自己用 Rust 写的核心使用它们，并编译成 WebAssembly 在你的浏览器中运行。HideFile 运行的每个地方用的都是同一个核心，所以要检查的只有一份实现，而不是每个平台一份。

<figure><img src="/docs/guides/img/product/04-set-password-desktop.jpg" alt="HideFile 中的 Set a password 步骤：被遮盖的密码、标为 Strong 的绿色强度条和 Create locked file 按钮。" loading="lazy" width="100%"><figcaption>密码是唯一的钥匙。点按 Create locked file 之后的停顿，就是 Argon2id 在工作。</figcaption></figure>

## 你锁定的任何东西都不会上传

锁定、解锁和保存都在浏览器标签页里完成。你的文件、文件名、密码和密钥都不会发送到 HideFile 的服务器，而且也没有任何存放上锁文件的 HideFile 服务器。唯一的例外是你自己开启的功能：如果你连接了自己的 S3 兼容存储桶，比如 Cloudflare R2，应用会把加密后的字节从你的设备直接发到那个存储桶，而不是发给我们。

应用确实会在你设备的浏览器中保存一些东西。为了让重新打开更快，它会保存你最近打开的那个上锁文件的一份副本（仍是加密的），最长一天、最大 100 MB。你保存下来以便重复使用的文件，以及打开中的文件的工作副本，存放在浏览器的私有文件存储里。它还会记住主题和视图之类的设置，以及你最近打开的十个封面的名称、大小和时间，但绝不会记住密码。清除网站数据会把这些全部删除。在共用或借来的电脑上，用完请这样做。

## 我们发送的分析数据不含任何文件数据

我们用 PostHog 统计使用情况，并且关闭了自动捕获，所以点按操作和页面内容都不会被记录。发送的内容有：

- 页面浏览：页面路径和来源网址、你的浏览器和设备类型，以及屏幕尺寸。
- 大致的国家或地区，由 PostHog 在请求到达时根据你的 IP 地址推算。
- 保存在你浏览器里的一个匿名随机标识符，用于统计重复访问。
- 三个事件：`locked_file_created`、`locked_file_opened` 和 `locked_file_saved`，每个只带封面类型（png、jpeg、mp4 或 pdf）和平台（web 或 native）。

文件名、大小、数量、路径、密码、密钥、内容和错误信息都不会发送。像 uBlock Origin 这样的内容拦截器会拦截这些分析，应用的使用不受影响。你可以自己验证：打开浏览器的开发者工具，在锁定和保存文件时观察“网络”（Network）标签，看有没有任何请求带着你的文件。[隐私政策](https://hidefile.app/privacy)才是这份清单具有约束力的版本。

<figure><img src="/docs/guides/img/product/security-what-leaves.svg" alt="留在你设备上的：你的文件、文件名和大小、你的密码、加密密钥、解锁后的内容和封面文件。发送给分析服务的：带路径和来源的页面浏览、浏览器、设备和屏幕尺寸、大致的国家或地区、一个匿名随机 ID，以及三个只带封面类型和平台的事件（创建、打开、保存）。只有你自己设置后才会发生的：加密后的字节发到你自己的 S3 或 R2 存储桶，而不是发给我们。应用的代码在你访问时从 hidefile.app 下载。" loading="lazy" width="100%"><figcaption>哪些留在你的设备上，以及离开设备的那份简短清单。</figcaption></figure>

## 威胁模型：按“谁”来说明

| 谁 | 结果 | 原因 |
|---|---|---|
| 翻看你的手机、笔记本电脑或云盘的人 | 能挡住 | 他们看到的是一张普通的照片、PDF 或视频，没有任何名字像保险箱的东西 |
| 知道你手机锁屏密码的人 | 能挡住 | 封面有自己的密码，与设备锁无关 |
| 拿到封面副本但没有密码的人 | 能挡住 | 内容保持加密 |
| 取证检查人员，或者知道 HideFile 并仔细检查的人 | 藏不住 | 他们能看出被加了数据；内容仍是加密的 |
| 能强迫你交出密码的人 | 挡不住 | 没有任何软件能解决这个问题 |
| 恶意软件、屏幕录制，或在已解锁设备旁边的窥视者 | 挡不住 | 文件打开期间，他们看到的就是你看到的 |

<figure><img src="/docs/guides/img/product/security-threat-model.svg" alt="能挡住的：翻看你的手机或笔记本电脑的人，他看到的是一张普通图片；知道你手机锁屏密码的人，因为封面有自己的密码；拿着副本但没有密码的人，因为内容保持加密。藏不住的：取证检查人员，他能看出被加了数据。挡不住的：能从你这里逼出密码的人，以及恶意软件或已解锁设备旁边的窥视者。" loading="lazy" width="100%"><figcaption>HideFile 能挡住随手窥探，挡不住取证工具。</figcaption></figure>

## 取证工具能看出被加了数据

HideFile 并不试图向取证检查隐瞒数据的存在，也没有这样声称。你的加密记录位于封面自己的文件结构之中，普通查看器会忽略它们。专门的工具，或者知道该找什么的检查人员，能识别出被加入了记录。文件大小是更简单的破绽：一张简短的度假快照带着几个 GB 就不寻常，把封面和没动过的原图一比就立刻看出差别。

检查人员得到的是“这里有东西”这个事实，而不是内容。没有密码，这些记录依然是封存的。这就是诚实的边界：“藏在眼皮底下”应对的是好奇的人和普通的搜查，而不是拿着你设备、决心已定的检查人员。边境检查、训练有素的检查人员或法律压力，它都不合适。

防篡改覆盖的是封存的记录，而不是封面的每一个字节。重新保存、去除元数据或重新压缩封面的 App，可以在加密毫无警报的情况下改动图片本身，还可能把记录整个去掉，这会毁掉里面的文件。请把封面当作文件保存。

## 密码无法找回

我们不持有你的密码，也无法从上锁文件里推出它。没有重置链接，没有恢复码，也没有任何客服流程能打开文件。密码丢了，里面的文件就丢了。这是设计本身的特性，也是持有你封面副本的人不能直接找我们来打开的原因。

## 哪些不是开源的，也没有经过审计

HideFile 的源代码没有公开，也没有独立机构审计过。算法是标准的，实现它们的库是开源的，本页和应用内的[安全页面](https://hidefile.app/security)给出了参数，但我们调用它们的代码，目前外人还读不到。

这很重要。有位 Hacker News 评论者在回应另一个把数据藏进照片的闭源工具时，用四个词概括了这一点：“no source code == no security.”（没有源代码就没有安全。）社区里还有人指出，网页应用每次访问都会从服务器重新下发，所以即使公开了源代码，也需要有办法确认你运行的代码与它一致。这两点都有道理，对按这个标准要求的读者来说，HideFile 目前还没有达到。我们宁愿直说，也不争辩。如果你发现了漏洞，请发邮件到 support@hidefile.app，附上复现步骤，并在公开之前给我们合理的时间发布修复。

## 资料来源

- HideFile：[How HideFile protects you](https://hidefile.app/security)
- HideFile：[Privacy Policy](https://hidefile.app/privacy)
- OWASP：[Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)
- RFC 9106：[Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications](https://www.rfc-editor.org/rfc/rfc9106)
- RustCrypto：[argon2 crate](https://docs.rs/argon2) 和 [chacha20poly1305 crate](https://docs.rs/chacha20poly1305)
- Hacker News：[Show HN: a hardware-bound local password vault hidden in a photo](https://news.ycombinator.com/item?id=49508206)，评论 [49509561](https://news.ycombinator.com/item?id=49509561)
- Hacker News：[comment on browser delivery of encrypted apps](https://news.ycombinator.com/item?id=19983075)
