Reputation: 13906
I used json to encrypt the values. However, I tried to decrypt the value again, but it was unsuccessful. The value is empty.
node.js source
import CryptoJS from 'crypto-js';
const EncryptHex = (string, chip) => {
let result = '';
try {
const key = CryptoJS.enc.Hex.parse(STORE_KEY);
if (chip === 'AES') {
const iv = CryptoJS.lib.WordArray.create([0x00, 0x00, 0x00, 0x00]);
result = CryptoJS.AES.encrypt(string, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
});
result = result.ciphertext.toString(CryptoJS.enc.Hex);
DecryptHex(result, 'AES', STORE_KEY);
} else {
result = CryptoJS.HmacSHA256(string, key).toString(CryptoJS.enc.Hex);
}
return result;
} catch (error) {
throw error;
}
};
const DecryptHex = (string, chip, skey) => {
let result = '';
const key = CryptoJS.enc.Hex.parse(skey);
const iv = CryptoJS.lib.WordArray.create([0x00, 0x00, 0x00, 0x00]);
try {
const array = CryptoJS.enc.Hex.parse(string);
if (chip === 'AES') {
result = CryptoJS.AES.decrypt(array, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
}).toString();
console.log('$$$$');
console.log('result : ', result);
console.log('$$$$');
} else {
result = array;
}
return result;
} catch (error) {
throw error;
}
};
log value
$$$$
result :
$$$$
What is the reason? How can I solve this problem?
Upvotes: 1
Views: 935
Reputation: 49141
CryptoJS.AES.decrypt
expects as ciphertext either a Base64 encoded string (which is implicitly converted into a CipherParams
object) or a CipherParams
object (see here).
Option 1 - The quick way: The ciphertext can be Base64 encoded in DecryptHex
e.g. with:
const array = CryptoJS.enc.Hex.parse(string).toString(CryptoJS.enc.Base64);
Alternatively EncryptHex
could also use a Base64 instead of a hex encoding.
Option 2 - The tidier way: The detour via Base64 encoding can be avoided by passing the ciphertext directly as CipherParams
object in CryptoJS.AES.decrypt
. To do this, simply replace array
with { ciphertext: array }
in CryptoJS.AES.decrypt
:
const array = CryptoJS.enc.Hex.parse(string);
result = CryptoJS.AES.decrypt({ ciphertext: array }, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
}).toString();
Note also that CryptoJS.AES.decrypt
returns the decrypted data as a WordArray
(see here), which is currently hex encoded with toString()
. With toString(CryptoJS.enc.Utf8)
the result is Utf8 decoded.
Upvotes: 2
Reputation: 30675
There are a couple of things we need to do, number 1, get the right key length, this should be either 128,192, or 256 bits long.
In this code I'm using a 256 bit key. Don't use this in production :)
Also, if you use the format: CryptoJS.format.Hex when decrypting, it will accept a hex encoded ciphertext.
This should encrypt and then decrypt a test message:
// Using a 256-bit key to ensure we use AES-256
STORE_KEY = "7246b9b8171743cd9cf285367a2fd5ad";
const EncryptHex = (string, chip, skey) => {
let result = '';
try {
const key = CryptoJS.enc.Hex.parse(skey);
if (chip === 'AES') {
const iv = CryptoJS.lib.WordArray.create([0x00, 0x00, 0x00, 0x00]);
result = CryptoJS.AES.encrypt(string, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
});
result = result.ciphertext.toString(CryptoJS.enc.Hex);
} else {
result = CryptoJS.HmacSHA256(string, key).toString(CryptoJS.enc.Hex);
}
return result;
} catch (error) {
throw error;
}
};
const DecryptHex = (encryptedStringHex, chip, skey) => {
let result = '';
const key = CryptoJS.enc.Hex.parse(skey);
const iv = CryptoJS.lib.WordArray.create([0x00, 0x00, 0x00, 0x00]);
try {
const array = CryptoJS.enc.Hex.parse(encryptedStringHex);
if (chip === 'AES') {
result = CryptoJS.AES.decrypt(encryptedStringHex, key, {
iv: iv,
format: CryptoJS.format.Hex,
mode: CryptoJS.mode.CBC,
}).toString(CryptoJS.enc.Utf8);
console.log('$$$$');
console.log('result : ', result);
console.log('$$$$');
} else {
result = array;
}
return result;
} catch (error) {
throw error;
}
};
let encrypted = EncryptHex("A good story cannot be devised; it has to be distilled", "AES", STORE_KEY);
console.log("Encrypted data:", encrypted);
console.log("Decrypted data:");
DecryptHex(encrypted, "AES", STORE_KEY);
Upvotes: 2