当指定 none 时,CryptoJS 如何获得 IV?

How does CryptoJS get an IV when none is specified?

当使用 CryptoJS.AES.encrypt 时,如果没有将第三个参数传递给函数,它如何得出初始化向量?有没有办法把它从加密字符串中取出来?

我需要这个的原因是我需要解密使用 Lua 返回的内容 CryptoJS.AES.encrypt,但我只有提供的密钥。

CryptoJS' CryptoJS.<BlockCipher>.encrypt 有两种加密模式。

  1. 如果您传入的密钥 不是字符串 ,而是 WordArray(CryptoJS 的二进制数据内部表示格式),则该密钥将被获取原样。此模式需要一个 IV 用于除 ECB 之外的所有操作模式,ECB 不使用 IV,因此您不必指定一个。如果没有传递 IV,它将默认(通过一些 JavaScript 魔法)为零填充 IV(由 0x00 字节的完整块组成)。

  2. 如果您传入一个 是字符串 的“密钥”,它将假定该“密钥”是密码。为了从密码中导出密钥,它使用了 OpenSSL 兼容的导出函数 EVP_BytesToKey。此模式生成一个新的 8 字节随机盐并将其与密码一起用于生成密钥和 IV。即使您显式传入 IV,它也不会被使用。

     CryptoJS.AES.encrypt(msg, password).toString()
    

    生成 Base64 编码的密文,其开头包含字符串“Salted__”,后跟 8 字节盐和实际密文。您可以在使用前明确拆分它:

     var ct = CryptoJS.AES.encrypt(msg, password);
     var saltHex = ct.salt.toString();     // random salt
     var ctHex = ct.ciphertext.toString(); // actual ciphertext
     var ivHex = ct.iv.toString();         // generated IV
    

    如果您需要重新创建相同的密钥派生。看看 the code and the specification.

    密钥应该具有高熵并且与随机噪声难以区分,这使得它们很难被暴力破解。上面提到的 EVP_BytesToKey 是不安全的,因为 MD5 散列非常快,这使得攻击者能够暴力破解密码。您要么需要使用非常长的密码(20-30 个字符),要么使用适当的密钥派生函数,例如 CryptoJS 提供的 PBKDF2。