客户端(JavaScript)文件上传加密

10
我正在尝试构建一种客户端加密文件并上传的方法。目标是将文件加密存储在服务器上,只有最终用户才能解密该文件。这个问题之前已经被问过,但我认为我取得了一些进展。
我的计划是使用新的Javascript文件API来操作文件并上传它。可以使用Stanford Javascript Crypto Library进行加密。应该分块读取文件,以便不会完全读入内存。然后,每个块都由加密库加密。我无法弄清如何实现此功能。作为一个开始,我有以下内容:
var fd = new FormData();
var file = document.getElementById('file').files[0];
fd.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/upload/");
xhr.send(fd);

这只是一个常规的JavaScript上传。我正在尝试构建一个模拟File对象行为并将其传递给FormData的Crypt对象。对于FormData读取的每个数据块,该对象应从文件中读取一个块并加密它。我仍然无法弄清楚FormData如何处理File对象以及是否可能复制此行为。我不确定是否这是正确的方法,有没有人有建议?

更新:好的,现在我进展很多了。我正在使用file.slice分块读取文件。然后加密每个块,并使用BlobBuilder将其转换回blob。然后将此blob放入FormData对象中并提交到服务器。服务器将连接这些blob。使用浏览器加密和解密一个块是可以工作的。现在我正在处理下载和解密多个块。

仍然有一些问题需要解决:

  • 文件的名称丢失了,目前还不能为文件对象设置FileName。
  • 加密仍然是阻塞的(没有UI更新),但我认为我可以用Webworkers来解决这个问题。
  • 我无法预测下载时的块大小。未加密的块大小已知,但对于加密数据,它似乎有所不同。这些加密数据以JSON形式存储,我不想对}进行字符串搜索。而且我希望不要把这些数据存储在服务器上。
  • 虽然我正在分块读取文件,但Firefox似乎存在内存泄漏或将整个文件读入内存。对于多吉字节的文件,这成为一个问题。

你想保护它免受谁的攻击?为什么不直接使用https? - Spudley
1
@Spudley 这当然取决于您想要在客户端加密文件以确保服务器端无法访问原始内容的情况下,这样的解决方案是必需的。 HTTPS 只能防止中间人获取访问权限。 - Remco Wendt
3
如果有人黑客攻击服务器,他们可以修改JS代码来收集密钥。此外,如果您不使用HTTPS,则中间人也可以这样做。加密可以使黑客攻击服务器后上传的文件更难解密,但在这种情况下,无论加密是在客户端还是服务器上进行,都没有区别。 - Ilmari Karonen
2
数据应该被加密存储。我们不希望在传输过程中发送未加密的数据或密钥。是的,我们将使用HTTPS。但是让服务器端进行加密意味着服务器需要密钥。服务器不应该有密钥的访问权限。数据的存储可能由第三方或最终在“云”中完成。我们希望加密尽可能靠近用户发生。 - Gijs Molenaar
其实,认为因为加密在服务器端完成,所以服务器需要密钥是完全错误的想法!您可以在用户登录时将密钥存储在会话中,这样服务器就没有存储密钥...有关更多详细信息,请参见我的答案。 - Vincent Pazeller
显示剩余8条评论
1个回答

6
以下是一种强烈保护文件的解决方案。
优点: - 攻击者可以访问服务器,但无法使用数据。 - 即使您(开发人员)也无法访问数据。
缺点: - 如果用户丢失密码,则数据也会丢失。 - 即使您(开发人员)也无法访问数据(这意味着如果用户遇到任何问题,您无法帮助用户)。
如果符合您的需求,请选择它 ^^。注意:以下所有操作均在服务器端进行。
1. 对于所有传输使用 https 2. 当用户登录时,创建用户密码的哈希值(例如 sha(password+salt)) 3. 将哈希存储在用户的会话中 4. 当上传完成时,使用对称加密(例如 AES)使用存储在会话中的哈希作为密钥加密数据。 5. 当下载完成时,使用相同的对称解密方法解密文件并将其发送回用户。
这意味着只有已登录的用户可以以明文形式访问数据。仅限于数据归属用户。要访问用户的数据的唯一可能性是知道他的密码。
注意:如果上传文件的用户和读取文件的用户不是同一个人,则可以改用非对称和对称加密的组合:
1. 为收件人生成公共/私有密钥对。 2. (对称)使用收件人的哈希或密码依赖性加密私钥。 3. (新)非对称加密似乎比对称加密慢得多(取决于算法/架构的10-100倍)。因此,最好生成一个随机数(会话密钥),两次使用非对称加密(一次使用发送方的公钥,一次使用收件人的公钥)进行加密并存储它们。然后使用对称加密来加密文件(使用明文会话密钥作为对称密钥)。 4. 当收件人想要访问文件时: a)使用他的哈希或密码相关性解密私钥。 b) (新)使用私钥来解密收件人的加密会话密钥。然后使用对称解密来解密文件。
希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接