我相信,因为传递给 AES.encrypt 的 key 是一个字符串,所以该函数将自动生成一个 IV。那么下面的代码是否生成了安全良好的 string_to_encrypt 加密版本?
pass = document.getElementById('pass').value; // user entered pwrd salt = 'some system determined salt';
its = 9000 + getKeyIterationModifier(pass); // iterations depend on pass
key = CryptoJS.PBKDF2(pass, salt, { keySize: 512/32, iterations: its });
encrypted = CryptoJS.AES.encrypt(string_to_encrypt, key.toString());
或者我应该添加“模式”和“填充”值以进一步强化它?如果是,当前的行业标准值是多少?
换句话说,理想情况下我是否应该使用以下内容(如果是自动完成的话,可能不需要 iv),如果是的话,什么是理想的:
key = CryptoJS.enc.Base64.parse(key);
encrypted = CryptoJS.AES.encrypt(string_to_encrypt, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
最佳答案
CryptoJS.AES.encrypt
使用 EVP_BytesToKey 将传递的“ key ”(视为密码)扩展为实际的 AES-256 key 和 IV(如果“ key ”是字符串)。它使用随机盐,因此密文是随机的。在第二个片段中,您需要自己处理 IV。
您实质上要问的是 EVP_BytesToKey 是否是安全的密码扩展函数。这不是一个可以轻易回答的问题。它使用 MD5 的事实意味着第一个片段至少具有 AES-128 的安全性,这应该很好。
另一个问题是,对于每一种加密,IV 都应该是不可预测的(即随机的)。不要使用静态 IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前何时发送过相同的消息前缀。第一个代码片段中给出了此建议,但您必须在第二个代码片段中实现该建议,这可能会引入其他问题。
如果您不熟悉 CryptoJS 和密码学,请使用第一个片段。否则,请尝试改进第二个片段。
<小时/>安全考虑:
如果您在浏览器中仅使用对称加密,则服务器和客户端需要完全相同的 key 。如果您将加密 key 从服务器发送到客户端或以其他方式发送加密 key ,则您需要加密对称加密 key 。最简单的方法是使用 TLS。如果您使用 TLS,那么数据和 key 都会被加密,因此您不需要自己加密。这不提供任何安全性,只是有点混淆。您应该阅读:https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
您应该考虑通过 GCM 或 EAX 等身份验证模式集成经过身份验证的加密,或者通过使用具有强大 MAC(如 HMAC-SHA256)的先加密后 MAC 方案来集成身份验证加密。
关于javascript - 这个 CryptoJS AES 加密代码会产生安全的输出吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43636332/