最近一直在琢磨网盘的端对端加密的方法,到今天才知道原来 Mega 就是端对端加密界的领军人物。读了他们的安全白皮书,受益匪浅,把主要过程记录下来。

用户注册

  1. 用户输入的密码会由ZXCVBN库来检测强度;

  2. 客户端生成随机128位的 Master key

  3. 生成一个128位随机数Client Random Value并用其产生 salt

Salt = SHA-256(“mega.nz” || “Padding” || Client Random Value)

  1. PBKDF2将用户输入密码导出成Drived key

Derived Key = PBKDF2-HAMC-SHA-512(Password, Salt, Iteration, Length)

其中Iteration值设为100,000,length为256位。

  1. Derived key的前半部分用于加密Master key

Encrypted Master Key = AES-ECB(Derived key, Master Key)

  1. Derived key的后半部分用于生成一个Hashed Authentication Key用于身份验证:

Hashed Authentication Key = SHA-256(Derived key)

  1. 客户端将下列信息发送给服务器完成注册:

Email

Client Random Value

Encrypted Master Key

Hashed Authentication Key

  1. 在客户第一次登录时,还会产生一对 RSA密钥,其公钥和加密过的私钥被保存到服务器。

最终结果,服务器端保存了用户加密过的Master key,加密过的私钥,Hashed过的Authentication key,未加密的公钥和 用于计算Salt值的Client Random Value。

用户登录

  1. 用户输入 Email 和密码;

  2. Email被发到服务器并检查是否存在于数据库中,如果成功的话则返回用户的 Salt值,否则将返回一个由随机数生成的 Salt值。此过程引入一个随机延迟,以防止时间攻击;

  3. 客户端根据输入的密码和得到的 Salt值算出 Derived Key

  4. Derivded Key的后半部分发给服务器进行验证,匹配的话证明用户密码正确,服务器返回用户加密过的Master Key、私钥和一个由公钥加密的Session ID

  5. 客户端使用Derived Key解密Master Key,后者再用于解密私钥,再用私钥解密Session ID

  6. 客户端在后续请求中均附上Session ID以表明身份。

文件上传

  1. 客户端生成一个128位的随机值和64位的随机nonce组成的File Key

  2. 将文件分块,每一块都用AES-CCM加密,nonce值随加密过程递增;

  3. 所有块加密完成后,生成消息验证码MAC

  4. 混淆File KeyObfuscated File Key

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    Obfuscated File Key = [
        File Key[0] XOR IV[0],
        File Key[1] XOR IV[1],
        File Key[2] XOR MAC[0] XOR MAC[1],
        File Key[3] XOR MAC[2] XOR MAC[3],
        IV[0],
        IV[1],
        MAC[0] XOR MAC[1],
        MAC[2] XOR MAC[3]
    ];
  1. 加密Obfuscated File Key并上传至服务器:

Encrypted File Key = AES-ECB(Master key, Obfuscated File Key)

  1. 加密文件元信息并上传:

Encrypted File Attr = AES-CBC(File Key, File Attr Data)

这里只是一个大概,详细的过程可以参阅 Mega发布的安全白皮书: https://mega.nz/SecurityWhitepaper.pdf

后话

但是目前我还对两个问题有疑问:

  • 再次登录时不要求输入密码,说明Mega一定保存了一些东西在浏览器里,要么是密码(或解密的主密钥或私钥),要么是身份验证的凭据。但根据白皮书看来,验证凭据只是一个Session ID,理论上不会保存很久,所以它在浏览器里保存了密码/私钥?

  • 理论上绝大部分文件操作,不管是浏览目录,还是预览文件,都需要用户密码,但是实际使用过程从没让我输入过,这也加深了我的疑惑。

所以也很好理解为什么主流网盘都不支持端对端加密,纯粹是出力不讨好。加密必然影响性能和用户体验,Mega如果真的不保存密码,每次操作都让我输密码,我也得烦死,但它要是保存了密码,我又要担心它的安全性。现在试图实现端对端的加密的私有云,不管是Nextcloud还是Seafile,都因加密措施不够严谨而广受诟病。反过来,谷歌云盘、dropbox之类的大厂干脆不支持加密,想加密的自己去用Cryptomator,反而落得省心。

八卦

在查Mega资料的过程中还发现了一段很有意思的八卦。创始人Kim Dotcom是一个德裔芬兰人,他90年代初黑入电话公司的数据库被判了两年缓刑,并因此暴得大名。2005年创办Megaupload,并移居新西兰。2012年网站被强制关闭,他在新西兰的家里被FBI破门而入,以洗钱、侵权、电信诈骗等罪名起诉,不过一直没有被引渡到美国。此事直到现在还没消停,BBC还有去年11月的后续报道。2013年他又创办了Mega,2015年他宣布退出,原因是Mega被闫永明(“中国伟哥之父”,因涉嫌职务侵占罪出逃到新西兰)恶意收购。2016年,闫永明与新西兰法院达成和解,代价是4000多万新币和18.8%的股份,所以现在Mega约等于一个新西兰的国企。