Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
412 views
in Technique[技术] by (71.8m points)

javascript - CryptoJS and key/IV length

I have question about AES key and IV length.

First of all, if, for example, I'm using drugs OpenSSL extension and openssl_encrypt() method, I can clearly see that key for 256-bit AES should be 32 bytes, and IV throws warning if it's different than 16 bytes. I can understand that, and everything is fine.

However, in CryptoJS library the key and IV length is frustrating. This is some example:

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 });

where key is 32 bytes, IV is 16. CryptoJS requires to parse it, and after CryptoJS.enc.Base64.parse() I get 48 and 24 bytes accordingly. I expect that those values will get truncated to required 256-bit AES length, and further expansion to n bytes will be irrelevant, and so resulting ciphertext will be the same.

But that's not actually happening. When I pass to CryptoJS.AES.encrypt() larger size key and even IV, it's producing different output. So my question is, why? What is the difference between CryptoJS library and OpenSSL in this case?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Looks like I've got it.

If you tend to pass custom key and IV in using CryptoJS, make sure that (assuming that CryptoJS.enc.Base64.parse() gives HEX string, which is used in CryptoJS.AES.encrypt()).

Taking this example, with Base64 key and iv (length=22), which CryptoJS encrypts as 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"

Length of the key is 32 bytes for AES-256. (16 bytes if you want to get AES-128. If more, CryptoJS will switch to higher key length). In other case on decrypt you will get an empty message. Example:

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

Also, from what I can see, only x % 8 == 0 bytes of such use case gives valid result.

Length of IV should be 22 bytes (when Base64 encoded), and while transforming with CryptoJS.enc.Base64.parse() you will get 16 bytes (32 hex encoded), which is max for AES-256 block size. Everything more than that will get truncated.

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...