这个 CryptoJS AES 加密代码会产生安全输出吗?

Will this CryptoJS AES encryption code produce secure output?

我相信因为传递给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());

或者我应该添加 'mode' 和 'padding' 值以进一步强化它吗?如果是,当前的行业标准值是多少?

换句话说,我是否应该理想地使用 类似 的东西(如果自动完成,可能没有 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
});
如果 "key" 是字符串,

CryptoJS.AES.encrypt 使用 EVP_BytesToKey 将传递的 "key"(视为密码)扩展为实际的 AES-256 密钥和 IV。它为此使用随机盐,因此密文是随机的。在你的第二个片段中,你需要自己处理 IV。

您实质上要问的是 EVP_BytesToKey 是否是安全密码扩展函数。这不是一件容易回答的事情。它使用 MD5 的事实意味着第一个片段 至少 AES-128 的安全性应该很好。

另一个问题是 IV 对于绝对每次加密都应该是不可预测的(读取:随机)。不要使用静态 IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。第一个片段中给出了这个建议,但您必须在第二个片段中实现该建议,这可能会引入其他问题。

如果您对 CryptoJS 和密码学不熟悉,请阅读第一个代码段。否则,请尝试改进第二个代码段。


安全注意事项:

如果您在浏览器中只使用对称加密,您需要在服务器和客户端使用完全相同的密钥。如果您将加密密钥从服务器发送到客户端或以其他方式发送,您需要加密您的对称加密密钥。最简单的方法是使用 TLS。如果您使用 TLS,那么数据和密钥都会被加密,因此您不需要自己加密。这不提供任何安全性,只是有点混淆。你应该阅读:https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/

您应该考虑通过像 GCM 或 EAX 这样的身份验证模式集成身份验证加密,或者通过使用像 H[=35 这样具有强 MAC 的加密然后 MAC 方案=]-SHA256.