关于javascript:CryptoJS和密钥/ IV长度

CryptoJS and key/IV length

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

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

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

1
2
3
4
5
6
7
8
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个字节将是无关紧要的,因此所得的密文将是相同的。

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


看起来我知道了。

如果您倾向于在使用CryptoJS时传递自定义keyIV,请确保这样做(假设CryptoJS.enc.Base64.parse()给出了在CryptoJS.AES.encrypt()中使用的十六进制字符串)。

以Base64密钥和iv(长度= 22)为例,CryptoJS将其加密为AES-256:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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-256,key的长度为32个字节。 (如果要获得AES-128,则为16个字节。如果更多,CryptoJS将切换为更长的密钥长度)。 在其他情况下,解密时您会收到一条空消息。 例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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块大小是最大的。 超出此限制的所有内容都会被截断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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.