Can't decrypt string with CryptoJS

Viewed 26281

I'm trying to encode/decode data using CryptoJS, as a preliminar test for the code I want to develop. This is the code I'm using for encrypting:

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
var message = "Secret Message";
var key = CryptoJS.enc.Hex.parse('36ebe205bcdfc499a25e6923f4450fa8');
var iv  = CryptoJS.enc.Hex.parse('be410fea41df7162a679875ec131cf2c');

// Encription. Works ok
var encrypted = CryptoJS.AES.encrypt(
        message,key,
        {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }
    );
console.log('encrypted:'+encrypted.ciphertext.toString());
<script>

This is the first test I use for decrypting. It works OK, returning 3f0e590d2617dc7007b89350bd590409

// Decription. Works ok with "encrypted" parameter
var decrypted = CryptoJS.AES.decrypt(
        encrypted,key,
        {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }
    );
console.log('decrypted:'+decrypted.toString(CryptoJS.enc.Utf8));

Let's notice that encrypted parameter is the results from the previous call to CryptoJS.AES.encrypt. It's an object.

The problem I have is when I try to decrypt directly the string:

// Decription. It fails with manual data
var manual_data = CryptoJS.enc.Hex.parse('3f0e590d2617dc7007b89350bd590409');
var decrypted = CryptoJS.AES.decrypt(
        manual_data,key,
        {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }
    );
console.log('decrypted, by hand:'+decrypted.toString(CryptoJS.enc.Utf8));

It returns an "empty" object (an empty string in the above example). It seems like there is some data that CryptoJS.AES.decrypt needs which is stored into the encrypted object of the first example but missing from the wordarray of the second example.

Does anybody knows why is this happening?

2 Answers

If you still prefer to use the ciphertext, by default the when no encoding is passed into the ciphertext.toString(), it'll return a CryptoJS.enc.Hex.stringify on the ciphertext WordArray.

Since decrypt takes in text as a base64 string, you will need to call the following on your ciphertext hex string before you pass it back into decrypt.

CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(encrypted.ciphertext.toString()))

so in the case,

var manual_data = '3f0e590d2617dc7007b89350bd590409';
var base64_data = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(manual_data))
var decrypted = CryptoJS.AES.decrypt(
  base64_data,
  key,
  {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  }
);
console.log('decrypted by hand: '+decrypted.toString(CryptoJS.enc.Utf8));
Related