Java to JS and JS to Java encryption using cryptojs

P. Lalonde picture P. Lalonde · May 21, 2015 · Viewed 10.9k times · Source

I got on this post a couple of weeks ago and worked perfectly: Compatible AES algorithm for Java and Javascript

Now, I need to do the reverse operation, but once in java, I am getting this exception:

javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)

This is my "reverse" operation I did in JavaScript:

var rkEncryptionKey = CryptoJS.enc.Base64.parse('u/Gu5posvwDsXUnV5Zaq4g==');
var rkEncryptionIv = CryptoJS.enc.Base64.parse('5D9r9ZVzEYYgha93/aUK2w==');

function encryptString(stringToEncrypt) {
    var utf8Stringified = CryptoJS.enc.Utf8.parse(stringToEncrypt);
    var encrypted = CryptoJS.AES.encrypt(utf8Stringified.toString(), rkEncryptionKey, {mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv: rkEncryptionIv});
    return CryptoJS.enc.Base64.parse(encrypted.toString()).toString();
}

I though this would be all?

[EDIT]

Encrypted string is the following: {"company_name":"asdfasdfasd","customer_name":"asdfasdfasdfasdf","phone_number":"asdfasdfasdfasdf","email":"asdfasdfasdfasdfads"}

When doing the encrypt / decrypt from java to java it works, when doing so from java to javascript, also works, but from javascript to java, not working.

Java Code

public String toJson(final String encrypted) {
    try {
        SecretKey key = new SecretKeySpec(Base64.decodeBase64("u/Gu5posvwDsXUnV5Zaq4g=="), "AES");
        AlgorithmParameterSpec iv = new IvParameterSpec(Base64.decodeBase64("5D9r9ZVzEYYgha93/aUK2w=="));
        byte[] decodeBase64 = Base64.decodeBase64(encrypted);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, iv);

        return new String(cipher.doFinal(decodeBase64), "UTF-8");
    } catch (Exception e) {
        throw new RuntimeException("This should not happen in production.", e);
    }
}

Answer

Artjom B. picture Artjom B. · May 21, 2015

Change

return CryptoJS.enc.Base64.parse(encrypted.toString()).toString();

to

return encrypted.ciphertext.toString(CryptoJS.enc.Base64);

The encrypted object usually stringifies into an OpenSSL format which might also contain the salt. If you're only interested in the actual ciphertext, then you need to stringify the ciphertext property.

Note that toString() takes an optional encoding function. Use the one that you need.