Reputation: 437
This is sort of a part two to the question Trying to print hex string with CryptoJS
Basically, I have a function that uses CryptoJS to encrypt a message and spit out the cypher text as a hex string.
function EncryptAES(text, key) {
var encrypted = CryptoJS.AES.encrypt(text, key);
return encrypted.ciphertext.toString()
}
I want to write a function DecryptAES that takes the hex string, key, and salt (which I apparently need) and returns the original plaintext. The problem is I can't figure out how to get the hex string back into a form that CryptoJS.AES.decrypt
will accept, and I can't find anywhere in the documentation where it actually explains how to do it. Maybe I overlooked something. Please help.
Upvotes: 2
Views: 2600
Reputation: 1095
CryptoJS expects a certain format for its encrypted data. If you're supplying only the hexadecimal string of the ciphertext, you'll need to reconstruct this formatted data when decrypting. Here's an example:
function EncryptAES(text, key) {
var encrypted = CryptoJS.AES.encrypt(text, key);
return encrypted.toString(); // this will be a string includes salt, iv and ciphertext
}
function DecryptAES(ciphertext, key) {
var decrypted = CryptoJS.AES.decrypt(ciphertext, key);
return decrypted.toString(CryptoJS.enc.Utf8); // decode to original text
}
In the EncryptAES function, by calling encrypted.toString(), it will generate a string which includes salt, iv, and ciphertext. When we decrypt it, we don't need to handle salt and iv separately.
However, if you are only dealing with the ciphertext (hexadecimal string), you can decrypt it using:
function DecryptFromHex(ciphertextHex, key, iv) {
var cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Hex.parse(ciphertextHex)
});
var decrypted = CryptoJS.AES.decrypt(cipherParams, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv) });
return decrypted.toString(CryptoJS.enc.Utf8);
}
DecryptFromHex takes the hexadecimal ciphertext string, parses it back into a format that CryptoJS can understand, and then decrypts it. Note that the key and the iv are also parsed from UTF8 to the WordArray format that CryptoJS uses.
Ensure the key and iv you use for the decryption
match those used for encryption
.
Upvotes: -1
Reputation: 49460
CryptoJS uses the WordArray
data type internally and provides encoders for conversion. If you want to convert a hex encoded string into a WordArray
, this is possible with the Hex encoder as follows:
CryptoJS.enc.Hex.parse(<your hex encoded string>)
or the other way around
<your WordArray>.toString(CryptoJS.enc.Hex)
or for short
<your WordArray>.toString()
Moreover, CryptoJS.AES.encrypt()
returns a CipherParams
object that encapsulates ciphertext and salt, among other things. This CipherParams
object is to be passed to CryptoJS.AES.decrypt()
for decryption.
With this, what you want can be implemented as follows:
function EncryptAES(text, key) {
var encrypted = CryptoJS.AES.encrypt(text, key);
return {ciphertext: encrypted.ciphertext.toString(), salt: encrypted.salt.toString()}
}
function DecryptAES(ciphertext, salt, key){
var decrypted = CryptoJS.AES.decrypt({ciphertext:CryptoJS.enc.Hex.parse(ciphertext), salt:CryptoJS.enc.Hex.parse(salt)}, key);
return decrypted;
}
var {ciphertext, salt} = EncryptAES('The quick brown fox jumps over the lazy dog', 'my passphrase');
console.log('Ciphertext (hex): ', ciphertext);
console.log('Salt (hex): ', salt);
var decrypted = DecryptAES(ciphertext, salt, 'my passphrase');
console.log('Decrypted: ', decrypted.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
However, there is an easier way to handle salt and ciphertext. For a CipherParams
object, .toString()
returns the data in the Base64 encoded OpenSSL format consisting of the hex encoding of Salted__
followed by the 8 bytes salt and the actual ciphertext. CryptoJS.AES.decrypt()
implicitly converts such a Base64 string into a CipherParams
object:
var encrypted = CryptoJS.AES.encrypt('The quick brown fox jumps over the lazy dog', 'my passphrase').toString();
console.log("Salt, ciphertext (OpenSSL format, Base64): ", encrypted);
var decrypted = CryptoJS.AES.decrypt(encrypted, 'my passphrase');
console.log("Decrypted: ", decrypted.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
Upvotes: 4