我相信因为传递给AES.encrypt的密钥是一个字符串,该函数会自动生成一个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
});
答案 0 :(得分:1)
CryptoJS.AES.encrypt
使用EVP_BytesToKey来扩展传递的"键" (被认为是密码)到实际的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等经过身份验证的模式集成经过身份验证的加密,或者使用像HMAC-SHA256这样强大的MAC加密 - 然后MAC方案。