现有的利用SJCL、CryptoJS和/或WebCrypto的答案不一定是错误的,但它们并不像你最初怀疑的那样安全。通常你要用libsodium。首先我将解释为什么,然后如何。
为什么不是SJCL, CryptoJS, WebCrypto等?
简单的回答:为了让你的加密实际上是安全的,这些库希望你做出太多的选择,例如分组密码模式(CBC, CTR, GCM;如果你不知道我列出的三种方法中哪一种是安全的,在什么限制下使用,你根本不应该被这种选择所困扰)。
除非你的职位是密码学工程师,否则你很难安全地实现它。
为什么要避免使用CryptoJS?
CryptoJS提供了一些构建块,并希望您知道如何安全地使用它们。它甚至默认为CBC模式(存档)。
为什么CBC模式不好?
阅读这篇关于AES-CBC漏洞的文章。
为什么要避免WebCrypto?
WebCrypto是一种家常便饭的标准,由委员会设计,目的与密码学工程正交。具体来说,WebCrypto旨在取代Flash,而不是提供安全性。
为什么要避免SJCL?
SJCL的公共API和文档要求用户使用人类记住的密码加密数据。这几乎不是你在现实世界中想要做的事情。
此外:它的默认PBKDF2轮计数大约是您想要的86倍。AES-128-CCM可能没问题。
在上述三种选择中,SJCL是最不可能以悲剧收场的。但也有更好的选择。
为什么利布纳更好?
您不需要在密码模式、散列函数和其他不必要的选项之间进行选择。您永远不会冒险搞砸参数并从协议中移除所有安全性。
相反,libsodium只是为您提供了一些简单的选项,以实现最大的安全性和最少的api。
Crypto_box () / crypto_box_open()提供经过身份验证的公钥加密。
所讨论的算法结合了X25519 (ECDH over Curve25519)和XSalsa20-Poly1305,但是您不需要知道(甚至不需要关心)就可以安全地使用它
Crypto_secretbox () / crypto_secretbox_open()提供共享密钥认证加密。
这里讨论的算法是XSalsa20-Poly1305,但您不需要知道/关心
此外,libsodium在许多流行的编程语言中都有绑定,因此很可能只有在尝试与另一种编程堆栈进行互操作时,libsodium才能工作。而且,libsodium的速度非常快,而且不会牺牲安全性。
如何在JavaScript中使用Libsodium ?
首先,你需要决定一件事:
您只是想加密/解密数据(可能仍然以某种方式在数据库查询中安全地使用明文),而不担心细节吗?还是……
您是否需要实现特定的协议?
如果您选择了第一个选项,请获取CipherSweet.js。
相关文档可以在网上找到。EncryptedField对于大多数用例来说已经足够了,但是如果有很多不同的字段需要加密,那么EncryptedRow和EncryptedMultiRows api可能会更容易一些。
有了CipherSweet,你甚至不需要知道什么是nonce/IV就可以安全地使用它。
此外,它处理int/float加密,而不会通过密文大小泄露有关内容的事实。
否则,您将需要钠加,这是一个用户友好的前端,以各种libsodium包装。Sodium-Plus允许您编写易于审核和推理的高性能、异步、跨平台代码。
要安装钠加,只需运行…
npm install sodium-plus
目前没有浏览器支持的公共CDN。这种情况很快就会改变。但是,如果你需要的话,你可以从最新的Github版本中获取sodium-plus.min.js。
const { SodiumPlus } = require('sodium-plus');
let sodium;
(async function () {
if (!sodium) sodium = await SodiumPlus.auto();
let plaintext = 'Your message goes here';
let key = await sodium.crypto_secretbox_keygen();
let nonce = await sodium.randombytes_buf(24);
let ciphertext = await sodium.crypto_secretbox(
plaintext,
nonce,
key
);
console.log(ciphertext.toString('hex'));
let decrypted = await sodium.crypto_secretbox_open(
ciphertext,
nonce,
key
);
console.log(decrypted.toString());
})();
关于sodium-plus的文档可以在Github上找到。
如果您想要一个循序渐进的教程,这篇dev.to文章可以满足您的需要。