Open alexandrsek opened 1 year ago
I have the same problem
I decided to just rewrite the encryption with node-forge and it ended up working correctly...
I have the similar problem when I try to use binary key of AES.encrypt instead of plain string password.
import crypto from 'crypto-js'
// write a simple ase encryption function test
const encrypt = (text, key) => {
return crypto.AES.encrypt(text, key).toString() // key is a string, and it works without iv cfg
}
const encryptViaByte = (text, key) => {
// return crypto.AES.encrypt(text, crypto.enc.Hex.parse(key), { iv: crypto.enc.Hex.parse('') }).toString() // key is a non string, and it works only you set iv cfg
return crypto.AES.encrypt(text, crypto.enc.Hex.parse(key)).toString() // without iv cfg, TypeError: Cannot read properties of undefined (reading '0') will be thrown and from the final stack frame, it is iv is undefined, why not default iv to empty string?
}
encrypt('hello world', '1234')
encryptViaByte('hello world', '010203')
Liu.D.H crypto-js-demo 221ms 00:27 > node index.js
D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:371
words[offset + i] ^= block[i];
^
TypeError: Cannot read properties of undefined (reading '0')
at Object.xorBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:371:44)
at Object.processBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:314:27)
at Object._doProcessBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:486:25)
at Object._process (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\core.js:632:27)
at Object._doFinalize (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:501:46)
at Object.finalize (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:163:44)
at Object.encrypt (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:685:41)
at Object.encrypt (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:201:59)
at encryptViaByte (file:///D:/code/node/playground/crypto-js-demo/index.js:10:23)
at file:///D:/code/node/playground/crypto-js-demo/index.js:14:1
Node.js v20.11.1
Liu.D.H crypto-js-demo 164ms 00:34 >
Here is the related code of final stack frame, iv
is undefined and the go to else branch and block
is undefined too.
// Choose mixing block
if (iv) {
block = iv;
// Remove IV for subsequent blocks
this._iv = undefined;
} else {
block = this._prevBlock;
}
// XOR blocks
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= block[i];
}
The simple workaround is update the line to block = this._prevBlock || [0];
.
I have the similar problem when I try to use binary key of AES.encrypt instead of plain string password.
import crypto from 'crypto-js' // write a simple ase encryption function test const encrypt = (text, key) => { return crypto.AES.encrypt(text, key).toString() // key is a string, and it works without iv cfg } const encryptViaByte = (text, key) => { // return crypto.AES.encrypt(text, crypto.enc.Hex.parse(key), { iv: crypto.enc.Hex.parse('') }).toString() // key is a non string, and it works only you set iv cfg return crypto.AES.encrypt(text, crypto.enc.Hex.parse(key)).toString() // without iv cfg, TypeError: Cannot read properties of undefined (reading '0') will be thrown and from the final stack frame, it is iv is undefined, why not default iv to empty string? } encrypt('hello world', '1234') encryptViaByte('hello world', '010203')
Liu.D.H crypto-js-demo 221ms 00:27 > node index.js D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:371 words[offset + i] ^= block[i]; ^ TypeError: Cannot read properties of undefined (reading '0') at Object.xorBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:371:44) at Object.processBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:314:27) at Object._doProcessBlock (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:486:25) at Object._process (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\core.js:632:27) at Object._doFinalize (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:501:46) at Object.finalize (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:163:44) at Object.encrypt (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:685:41) at Object.encrypt (D:\code\node\playground\crypto-js-demo\node_modules\crypto-js\cipher-core.js:201:59) at encryptViaByte (file:///D:/code/node/playground/crypto-js-demo/index.js:10:23) at file:///D:/code/node/playground/crypto-js-demo/index.js:14:1 Node.js v20.11.1 Liu.D.H crypto-js-demo 164ms 00:34 >
Here is the related code of final stack frame,
iv
is undefined and the go to else branch andblock
is undefined too.// Choose mixing block if (iv) { block = iv; // Remove IV for subsequent blocks this._iv = undefined; } else { block = this._prevBlock; } // XOR blocks for (var i = 0; i < blockSize; i++) { words[offset + i] ^= block[i]; }
The simple workaround is update the line to
block = this._prevBlock || [0];
.
Maybe a more nice solution is set a default cfg option if the third argument is not passed. Change
cfg: Base.extend(),
to cfg: Base.extend({iv: WordArray.create()}),
in
Then the cfg in encrypt/decrypt will work as expected.
I tested with the following code, it works for me.
// test1.js
import CryptoJS from 'crypto-js'
// 生成随机密钥和 IV
const key = CryptoJS.lib.WordArray.random(256 / 8); // 256 位密钥
const iv = CryptoJS.lib.WordArray.random(128 / 8); // 128 位 IV
const plaintext = "This is some plaintext to encrypt.";
// encrypt
const encrypted = CryptoJS.AES.encrypt(plaintext, key);
console.log("encrypted text:", encrypted.toString());
// decrypt
const decrypted = CryptoJS.AES.decrypt(encrypted, key);
const decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
console.log("decrypted text:", decryptedText);
CryptoJS throws error when we pass AES key as WordArray. Here is a sample code to get this error.
And this is what I get
The simple solution would be to pass key as a string, but in the project I'm working on we can only decrypt when we pass key as CryptoJS.enc.Utf8.parse().