CryptoJS AES encryption and JAVA AES decryption value mismatch

11,382

Your Java code is riddled with errors. Here are a few of them:

  • Your initial exception is caused because your "Secret Passphrase" string contains 17 bytes. You need to truncate this to 16 bytes (or pad it to match 24 or 32 bytes). You need to match the behaviour of the CryptoJS library.

  • You are trying to hex-decode data that appears to be base64 encoded. Try using DatatypeConverter.parseBase64Binary(hex);.

  • You are creating a secret key with the algorithm "AES/CTR/NoPadding". This in invalid, just use "AES".

  • You must pass an IV/nonce value into your decryption:

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(...));
    

    The value you use will depend upon what CryptoJS is doing. Perhaps it uses all zeroes? Perhaps it generates a random one and you need to store it with the ciphertext?

This should be enough to get you started.

Share:
11,382
Muthu
Author by

Muthu

Passionate programmer.

Updated on June 04, 2022

Comments

  • Muthu
    Muthu almost 2 years

    I am encrypting a text using CryptoJS AES algorithm on the client side and I am decrypting It on Server side in java, I am getting the exception.

    JS code :

    var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
    console.info("encrypted " + encrypted);
    var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
    var plainText = decrypted.toString(CryptoJS.enc.Utf8)
    console.info("decrypted " + plainText);
    

    js output :

    encrypted U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=
    decrypted Message
    

    Java Code :

    import java.nio.charset.Charset;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.util.regex.Pattern;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    public class AESJavaScript {
        private SecretKeySpec key;
        private Cipher cipher;
        private int size = 128;
        private static final Charset CHARSET = Charset.forName("UTF-8"); 
    
        public AESJavaScript() throws NoSuchAlgorithmException,
                NoSuchPaddingException, NoSuchProviderException {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(size); // 192 and 256 bits may not be available
            SecretKey skey = kgen.generateKey();
            byte[] raw = skey.getEncoded();
            key = new SecretKeySpec(raw, "AES/CTR/NoPadding");
            cipher = Cipher.getInstance("AES/CTR/NoPadding");
        }
    
        public void setKey(String keyText) {
            byte[] bText = new byte[size];
            bText = keyText.getBytes(CHARSET);
            key = new SecretKeySpec(bText, "AES/CTR/NoPadding");
        }
    
        public String encrypt(String message) throws InvalidKeyException,
                IllegalBlockSizeException, BadPaddingException {
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(message.getBytes());
            return byteArrayToHexString(encrypted);
        }
    
        public String decrypt(String hexCiphertext)
                throws IllegalBlockSizeException, BadPaddingException,
                InvalidKeyException {
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexCiphertext));
            return byteArrayToHexString(decrypted);
        }
    
        private static String byteArrayToHexString(byte[] raw) {
            String hex = "0x";
            String s = new String(raw);
            for (int x = 0; x < s.length(); x++) {
                char[] t = s.substring(x, x + 1).toCharArray();
                hex += Integer.toHexString((int) t[0]).toUpperCase();
            }
            return hex;
        }
    
        private static byte[] hexStringToByteArray(String hex) {
            Pattern replace = Pattern.compile("^0x");
            String s = replace.matcher(hex).replaceAll("");
    
            byte[] b = new byte[s.length() / 2];
            for (int i = 0; i < b.length; i++) {
                int index = i * 2;
                int v = Integer.parseInt(s.substring(index, index + 2), 16);
                b[i] = (byte) v;
            }
            return b;
        }
    
        public static void main(String[] args) {
            try {
                AESJavaScript ajs = new AESJavaScript();
                ajs.setKey("Secret Passphrase");
                String hexCiphertext = "U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=";
                String decrypted = ajs.decrypt(hexCiphertext);
                System.out.println("decrypted > " + decrypted);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    

    Exception is :

    java.security.InvalidKeyException: Invalid AES key length: 17 bytes
        at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372)
        at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
        at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010)
        at javax.crypto.Cipher.implInit(Cipher.java:786)
        at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
        at javax.crypto.Cipher.init(Cipher.java:1213)
        at javax.crypto.Cipher.init(Cipher.java:1153)
        at com.test.jenkins.jenkinsRestart.AESJavaScript.decrypt(AESJavaScript.java:49)
        at com.test.jenkins.jenkinsRestart.AESJavaScript.main(AESJavaScript.java:82)
    

    Is there anything that I am doing wrong here or Is there anyother simple way to do these kind of encryption and decryption ?