【问题标题】:CryptoJS and key/IV lengthCryptoJS 和密钥/IV 长度
【发布时间】:2015-04-08 11:05:01
【问题描述】:

我对 AES 密钥和 IV 长度有疑问。

首先,例如,如果我使用 drugs OpenSSL 扩展和 openssl_encrypt() 方法,我可以清楚地看到 256 位 AES 的密钥 应该是 32 字节,如果它不同于 16 字节,IV 会抛出警告。我可以理解,一切都很好。

但是,在 CryptoJS 库中,密钥和 IV 长度令人沮丧。这是一个例子:

var text = "test",
    key  = "us5N0PxHAWuIgb0/Qc2sh5OdWBbXGady",
    iv   = "zAvR2NI87bBx746n";

key = CryptoJS.enc.Base64.parse(key);
iv  = CryptoJS.enc.Base64.parse(iv);

crypted = CryptoJS.AES.encrypt(text, key, { iv: iv });

其中 key 为 32 字节,IV 为 16。 CryptoJS 需要解析它,在CryptoJS.enc.Base64.parse() 之后,我相应地得到 48 和 24 个字节。我希望这些值将被截断为所需的 256 位 AES 长度,并且进一步扩展到 n 字节将是无关紧要的,因此生成的密文将是相同的。

但这实际上并没有发生。当我传递给 CryptoJS.AES.encrypt() 更大尺寸的密钥和 even IV 时,它会产生不同的输出。所以我的问题是,为什么?在这种情况下,CryptoJS 库和 OpenSSL 有什么区别?

【问题讨论】:

    标签: javascript cryptojs


    【解决方案1】:

    看来我明白了。

    如果您倾向于在使用 CryptoJS 时传递自定义 keyIV,请确保(假设 CryptoJS.enc.Base64.parse() 给出 HEX 字符串,使用在CryptoJS.AES.encrypt()) 密钥长度与块大小匹配。

    举这个例子,使用 Base64 密钥和 iv (length=22),CryptoJS 加密为 AES-256

    var message = "some_secret_message";
    
    var key = "6Le0DgMTAAAAANokdEEial"; //length=22
    var iv  = "mHGFxENnZLbienLyANoi.e"; //length=22
    
    key = CryptoJS.enc.Base64.parse(key);
    //key is now e8b7b40e031300000000da247441226a, length=32
    iv = CryptoJS.enc.Base64.parse(iv);
    //iv is now 987185c4436764b6e27a72f2fffffffd, length=32
    
    var cipherData = CryptoJS.AES.encrypt(message, key, { iv: iv });
    
    var data = CryptoJS.AES.decrypt(cipherData, key, { iv: iv });
    //data contains "some_secret_message"
    

    对于 AES-256key 的长度为 32 个字节。 (如果你想获得 AES-128 则需要 16 个字节。如果更多,CryptoJS 将切换到更高的密钥长度)。在其他情况下,解密时您将收到一条空消息。示例:

    var message = "some_secret_message";
            
    var key = "6Le0DgMTAAAAANokdEEial1"; //length=23
    var iv  = "mHGFxENnZLbienLyANoi.e"; //length=22
            
    key = CryptoJS.enc.Base64.parse(key); // length = 17 bytes
    //key is now e8b7b40e031300000000da247441226a5d, length=34 (hex encoded)
    iv = CryptoJS.enc.Base64.parse(iv); // length = 16 bytes
    //iv is now 987185c4436764b6e27a72f2fffffffd, length=32 (hex encoded)
            
    var cipherData = CryptoJS.AES.encrypt(message, key, { iv: iv });
            
    var data = CryptoJS.AES.decrypt(cipherData, key, { iv: iv });
    //data contains "" - an empty string
    

    此外,据我所知,只有 x % 8 == 0 字节的此类用例给出有效结果。

    IV 的长度应该是 22 字节(使用 Base64 编码时),使用 CryptoJS.enc.Base64.parse() 进行转换时,您将得到 16 字节(32 十六进制编码),这是 AES-256 的最大值块大小。除此之外的所有内容都将被截断。

    var message = "some_secret_message";
    
    var key = "6Le0DgMTAAAAANokdEEial"; //length=22
    var iv  = "mHGFxENnZLbienLyANoi.e"; //length=22
    
    key = CryptoJS.enc.Base64.parse(key); // length=16 bytes
    //key is now e8b7b40e031300000000da247441226a5d, length=32 (hex encoded)
    iv = CryptoJS.enc.Base64.parse(iv); // length=16 bytes
    //iv is now 987185c4436764b6e27a72f2fffffffd, length=32 (hex encoded)
    
    var cipherData = CryptoJS.AES.encrypt(message, key, { iv: iv });
    
    var key = "6Le0DgMTAAAAANokdEEial"; //length=22
    var iv  = "mHGFxENnZLbienLyANoi.e123"; //length=25
    
    key = CryptoJS.enc.Base64.parse(key); // length = 16 bytes
    //key is now e8b7b40e031300000000da247441226a5d, length=32 (hex encoded)
    iv = CryptoJS.enc.Base64.parse(iv); // length = 18 bytes
    //iv is now 987185c4436764b6e27a72f2fffffffded76, length=36 (hex encoded)
    
    var data = CryptoJS.AES.decrypt(cipherData, key, { iv: iv }); //data contains "some_secret_message", so additional "123" in IV is irrelevant.
    

    【讨论】:

    • 1.你的号码有问题。 AES 的块大小为 128 位,这也是 IV 的预期大小。 AES 没有为大于或小于 16 字节的 IV 指定。 IV 大小与密钥大小不同。 2. 22 字节不是有效的 base64 编码字符串。它必须能被 4 整除(带有可选的填充字符)。
    • 我反对。如果是 AES-128,则 AES 的块大小为 128。在 AES-256 的情况下,块大小显然是 256 位,即 32 字节,这正是您通过 22 字节 Base64 字符串的CryptoJS.enc.Base64.parse() 得到的。根据规范和算法,IV 就是块大小长度,使用 AES-256 为 32 字节。
    • 如果您提到某些东西,请确保它支持您的主张:sqrt(23) 写道:“AES 恰好是众多 [...] 之一,具有恒定的块大小16 字节”“初始化向量,通常与密码的块大小匹配”。它不支持您的主张。密钥大小和块大小是不同的东西。 AES-256 中的 256 指的是密钥大小。
    • 适用于 AES-128。它说“初始化向量,它通常与密码的块大小相匹配”。对于分组密码操作模式,IV 通常与密码的分组大小一样大。因此,对于 256 位 AES,对我来说看起来像 32 字节。
    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    相关资源
    最近更新 更多