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 认证标签。如果某条记录被改动,不论是副本损坏还是有人故意改的,解锁都会报错失败,而不是悄悄返回错误的内容。

浏览器内部:密码和随机的 16 字节盐值进入 Argon2id(64 MiB 和 3 轮,手机和低内存浏览器为 19 MiB 和 2 轮),生成 32 字节的密码密钥。这个密钥包裹一个随机的 256 位文件密钥。XChaCha20-Poly1305 把文件封存成记录,每条记录带随机的 192 位 nonce 和防篡改标签。封存后的记录存放在封面文件内部。
一个密码,两把密钥。密码密钥只负责包裹文件密钥。

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

HideFile 中的 Set a password 步骤:被遮盖的密码、标为 Strong 的绿色强度条和 Create locked file 按钮。
密码是唯一的钥匙。点按 Create locked file 之后的停顿,就是 Argon2id 在工作。

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

锁定、解锁和保存都在浏览器标签页里完成。你的文件、文件名、密码和密钥都不会发送到 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)标签,看有没有任何请求带着你的文件。隐私政策才是这份清单具有约束力的版本。

留在你设备上的:你的文件、文件名和大小、你的密码、加密密钥、解锁后的内容和封面文件。发送给分析服务的:带路径和来源的页面浏览、浏览器、设备和屏幕尺寸、大致的国家或地区、一个匿名随机 ID,以及三个只带封面类型和平台的事件(创建、打开、保存)。只有你自己设置后才会发生的:加密后的字节发到你自己的 S3 或 R2 存储桶,而不是发给我们。应用的代码在你访问时从 hidefile.app 下载。
哪些留在你的设备上,以及离开设备的那份简短清单。

威胁模型:按“谁”来说明

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

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

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

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

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

密码无法找回

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

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

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

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

资料来源