开源云端文件加密工具 Cryptomator:让网盘服务商也打不开你的文件,深度解析其客户端加密机制
【免费下载链接】cryptomatorCryptomator for Windows, macOS, and Linux: Secure client-side encryption for your cloud storage, ensuring privacy and control over your data.项目地址: https://gitcode.com/GitHub_Trending/cr/cryptomator
网盘里的文件,服务商到底能不能打开?Cryptomator 给出的答案是:不能。这是一个开源的跨平台客户端加密工具,所有加解密都发生在你的设备上,云端的 Dropbox、OneDrive、Nextcloud 里存着的,只是一堆看不出名字也读不出内容的密文。本文基于仓库源码,把它的机制讲清楚。
端到端机制全景:从密码输入到虚拟盘符
整个系统可以概括成一条流水线:你在本地目录里建一个保险库(vault),放入密码;解锁时密码经 Scrypt 派生、解开主密钥文件,由此构建加密文件系统并挂载成一个普通磁盘;之后你对这个"盘"做的所有读写,都会被自动转成密文写回云端目录。
数据:云端目录里到底存着什么
保险库的加密目录里通常只有几样东西:masterkey.cryptomator(用你的密码保护的主密钥文件)、vault.cryptomator(配置文件,记录了加密方案和密钥派生参数),以及一堆文件名完全不可读的密文。
这套组织方式带来一个实际好处:每个密文文件都自带解密所需的元数据,保险库里没有共享的中心化元数据库。任何单点元数据损坏都不会拖垮整个库,同步客户端在不同设备之间丢一个"文件"也不会造成不可恢复的结构性损失。
另一个设计决定是文件名加密。普通加密工具只加密内容,而 Cryptomator 连文件名和目录结构都做了处理——README.txt在云端看起来是随机字符串,文件夹层级也被打乱。这意味着服务商不仅读不出内容,连"你存了哪些文件"这类元数据也拿不到。
密钥:主密钥如何生成、保存与销毁
密码本身从不出现在加密环节。解锁时密码只用来做一件事:通过 Scrypt 密钥派生函数,打开masterkey.cryptomator里被保护的主密钥。Scrypt 是内存密集型算法,暴力尝试每个密码候选的成本都很高,这层门槛挡在暴力破解面前。
源码里能看到密钥材料的两个形态(RecoveryKeyFactory):
byte[] rawKey = masterkey.getEncoded(); // 64 字节主密钥 Preconditions.checkArgument(paddedKey.length == 66, "Recovery key doesn't consist of 66 bytes."); Hashing.crc32().hashBytes(rawKey).writeBytesTo(paddedKey, 64, 2);64 字节(512 位)的主密钥是解密一切内容的根源。忘密码时的退路是恢复密钥:它就是主密钥的编码形式——用词列表把 64 字节编码成一串可读单词,尾部附加 2 字节 CRC16 校验和(上面第 64、66 两个字节)。抄写恢复密钥时漏一个字母,校验和不匹配,程序会直接告诉你不合法,而不是让你输完一整串才发现错了。用恢复密钥重置密码,本质是用它还原主密钥、再用新密码写一份新的主密钥文件。
流程:一次解锁经历了什么
解锁被组织成一个后台任务(UnlockWorkflow),密钥获取抽象成策略接口KeyLoadingStrategy,密码解锁与 Hub 解锁共用同一条流水线:
keyLoadingStrategy.use(vault::unlock); // 拿到 Masterkey 后交给 Vault 解锁Vault.unlock的内部顺序是:构建加密文件系统(Vault.java)→ 挂载到系统盘符 → 可选地加入"快速访问"。状态机在LOCKED → PROCESSING → UNLOCKED之间迁移,任何失败路径都会回到LOCKED,并区分处理挂载点冲突、只读文件系统等具体异常。锁定则是逆序:先卸载,再关闭文件系统,让主密钥随文件系统对象一起离开内存。
工程细节亮点
密码在内存里活不过一次使用。密码统一封装成Passphrase类型,底层是char[]而不是String(避免不可变字符串在堆里留下副本),实现了Destroyable接口,destroy()把字符数组整体清零。钥匙串管理器里即使只是探测"密码是否已存储",读出来的字符数组也在finally块里立即抹掉(KeychainManager)。
密码比较用了恒定时间。Passphrase.equals不是逐个字符短路返回,而是把所有差异位 OR 起来最后才判定,避免通过响应时间差猜出密码前缀:
int diff = 0; for (int i = 0; i < length; i++) { diff |= charAt(i) ^ that.charAt(i); } return diff == 0;解锁成功即自动备份主密钥文件。每次成功解锁后,如果主密钥文件就在保险库目录内,会顺手生成一份带时间戳的备份(BackupHelper.attemptBackup)。云端偶发的同步损坏不会让密码保护的主密钥永久丢失。
多账户网盘目录自动识别。对 Google Drive,macOS 版会扫描~/Library/CloudStorage/下形如GoogleDrive-账号的子目录,每个登录的账号各生成一条候选位置,而且识别"我的云端硬盘"时内置了几十种语言的翻译表——本地化不是 UI 层的事,目录探测也做了。这些探测器通过@OperatingSystem注解和@CheckAvailability静态检查过滤,只在对应平台、对应目录真实存在时才激活(LocationPresetsProvider)。
只读文件系统自动降级重试。如果挂载时目标目录不可写,解锁流程会弹窗询问是否以只读模式重试,而不是直接失败。
适合谁、怎么选
| 场景 | 更合适的方案 | 原因 |
|---|---|---|
| 网盘里的个人/敏感文件 | Cryptomator | 文件名与内容都加密,服务商不可见 |
| 自托管 Nextcloud/ownCloud | Cryptomator | 服务端加密策略不可靠时,客户端加密兜底 |
| 服务商需要检索/解析你的文件 | 服务商自带服务端加密 | 客户端加密后,服务端搜索等能力失效 |
| 本地设备整体丢失 | 全盘加密(BitLocker/FileVault) | 那是设备级防护,与文件级加密互补 |
| 多人协作编辑同一批文件 | 版本化协作工具 | 虚拟盘符的合并写不是它的目标场景 |
需要说明的边界:它依赖本地同步目录,所以只覆盖"有客户端目录同步"的云盘;本仓库是桌面应用(Windows/macOS/Linux)。保险库数量不设限,每个保险库独立密码、独立密钥;但一个保险库内的所有文件共享同一主密钥,把机密分开放进不同保险库是更稳妥的做法。
小结
密码不出本机,密钥不落云端:Cryptomator 用客户端加密把"信任服务商"降级成了"信任密码学",而开源代码让这种信任可以被逐行验证。
【免费下载链接】cryptomatorCryptomator for Windows, macOS, and Linux: Secure client-side encryption for your cloud storage, ensuring privacy and control over your data.项目地址: https://gitcode.com/GitHub_Trending/cr/cryptomator
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考