每次使用 CryptoJS 加密相同的文本时,输出都不同

Output is different every time when the same text is encrypted with CryptoJS

我对尝试使用 CryptoJS 加密某些东西浪费了很多时间感到非常沮丧,一段时间后,我意识到每次使用相同的输入加密结果都是不同的!这怎么可能?

这是我的代码,您可以检查它是否正确: https://jsfiddle.net/z5dg623q/1/

<script>
    function encrypt() {
        document.getElementById("stringOutput").value = CryptoJS.AES.encrypt("lorem ipsum", "hAPgT2mj0ZzD1epO").toString();
    }
</script>

<textarea id="stringOutput" cols="100" rows="10"></textarea>
<button type="button" onClick="encrypt()">Encrypt that!</button>

有人可以帮我吗?

当您将两个字符串传递给 CryptoJS.<Cipher>.encrypt() 时,您告诉 CryptoJS 使用基于密码的加密。它将假定第一个字符串是 UTF-8 编码数据,第二个字符串是将通过 MD5 发送以获得 256 位密钥和 128 位 IV 的密码。这是由所谓的 EvpKDF 完成的(参见 1 and 2) with a random salt (see here)。

这意味着在每次调用中,代码都会生成一个新的随机盐,然后每次都会使用该盐派生出不同的密钥和 IV,从而每次都会产生不同的密文。这种 属性 称为语义安全,例如可以防止攻击者仅通过查看密文来确定明文是否相等。这有时是至关重要的安全措施 属性.

当您在 encrypt() 结果上调用 toString() 时,它会将密文序列化为 OpenSSL 兼容格式,其中包括盐。所以你只需要密码和这个字符串就可以解密了。

当您尝试对其解密时,密文中的盐和您的密码用于派生用于加密的相同密钥和 IV。因此它可以恢复原来的明文。如果使用错误的密码,结果要么是空的,要么是乱码。

我遇到了同样的问题。这仅仅是因为我们不知道算法的工作原理。简单的说就是每次调用encrypt方法的key和IV都不一样,正如Artjom B在上面的回答中提到的。

确保每次迭代的值完全相同 - 你可以参考这个答案

或者,您可以使用 SHA3 函数并比较两个哈希值。