Using CryptoJS to encrypt in Javascript and decrypt in Java

mdagis picture mdagis · Oct 19, 2015 · Viewed 12.7k times · Source

I am trying to encrypt something in JavaScript using the google's https://code.google.com/p/crypto-js/#AES exactly as it is if the example. The problem is that where I am trying to decrypt it in Java the result is way different. The only difference that I can see is the padding (CryptoJs uses Pkcs7 whereas java uses Pkcs5) after reading a bit I realized that Pkcs7 and Pkcs5 are basically the same.

Here is a sample of the code that i do the encryption in Javascript:

var crypto = require('./aes.js');
var login = 'ABCD';
var key = crypto.CryptoJS.enc.Hex.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Hex.parse('0123456789012345');

var encrypted = crypto.CryptoJS.AES.encrypt(login, key, {iv: ive});
console.log('encrypted msg = ' + encrypted)

This is the code that I am using in Java to decrypt it:

public String decrypt(byte[] cipherText) throws Exception {

    String psk = "0123456789012345";
    String iv = "0123456789012345";
    try {
        String encryptionKey = psk;
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        final SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(UTF8), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes(UTF8)));
        return new String(cipher.doFinal(cipherText), UTF8);
    } catch (BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException ex) {
        LOG.log(Level.SEVERE, ex.getMessage(), ex);
        throw new Exception(ex.getMessage());
    }
}

Do you have any idea why it fails that bad? Is it a different algorithm or do I fail somewhere else?

Answer

Artjom B. picture Artjom B. · Oct 19, 2015

You're not using the same key and IV in CryptoJS and Java. The key and IV in the CryptoJS are too short to be valid, because you're parsing a 16 character string as Hex which results in only 8 bytes, but AES supports only key sizes of 128, 192 and 256 bit.

Use

var key = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');

Other considerations:

  • Always use a random IV. Since it doesn't have to be secret, you can prepend it to the ciphertext or send it along in another way.

  • Authenticate the ciphertexts with HMAC or use and authenticated mode like GCM to prevent some attacks such as padding oracle attack.