How to decrypt Cryptojs AES encrypted message on java server side?

I have the following cryptojs based javascript based encryption / decryption functions that work fine.

I use random salt, a random iv value and a specific password when encrypting a message using cryptpjs. I reuse the same salt, iv and password to generate the key when decrypting the encrypted message.

This part works well.

function encrypt(){ var salt = CryptoJS.lib.WordArray.random(128/8); var iv = CryptoJS.lib.WordArray.random(128/8); console.log('salt '+ salt ); console.log('iv '+ iv ); var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 }); console.log( 'key128Bits '+ key128Bits); var key128Bits100Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32, iterations: 100 }); console.log( 'key128Bits100Iterations '+ key128Bits100Iterations); var encrypted = CryptoJS.AES.encrypt("Message", key128Bits100Iterations, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); console.log('encrypted '+ encrypted ); } function decrypt(){ var salt = CryptoJS.enc.Hex.parse("4acfedc7dc72a9003a0dd721d7642bde"); var iv = CryptoJS.enc.Hex.parse("69135769514102d0eded589ff874cacd"); var encrypted = "PU7jfTmkyvD71ZtISKFcUQ=="; console.log('salt '+ salt ); console.log('iv '+ iv ); var key = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32, iterations: 100 }); console.log( 'key '+ key); var decrypt = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); var ddd = decrypt.toString(CryptoJS.enc.Utf8); console.log('ddd '+ddd); } 

But the problem starts when I try to decrypt the same encrypted text on the java server side. I want the encrypted message to be decrypted using java server code. Here is the Java code I wrote:

 public static void main(String args[]) throws Exception{ String password = "Secret Passphrase"; String salt = "4acfedc7dc72a9003a0dd721d7642bde"; String iv = "69135769514102d0eded589ff874cacd"; String encrypted = "PU7jfTmkyvD71ZtISKFcUQ=="; byte[] saltBytes = salt.getBytes(); //hexStringToByteArray(salt); byte[] ivBytes = iv.getBytes();//hexStringToByteArray(iv); IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); SecretKeySpec sKey = (SecretKeySpec) generateKeyFromPassword(password, saltBytes); System.out.println( decrypt( encrypted , sKey ,ivParameterSpec)); } public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException { KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128/32); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); SecretKey secretKey = keyFactory.generateSecret(keySpec); return new SecretKeySpec(secretKey.getEncoded(), "AES"); } public static String decrypt(String encryptedData, SecretKeySpec sKey, IvParameterSpec ivParameterSpec) throws Exception { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE, sKey, ivParameterSpec); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); return decryptedValue; } 

But I get the following exception:

 Exception breakpoint: SecretKeySpec.java:96, java.lang.IllegalArgumentException, Empty key Exception in thread "main" java.lang.IllegalArgumentException: Empty key at javax.crypto.spec.SecretKeySpec.<init>(SecretKeySpec.java:96) 

I have no idea what to do.

+7
java encryption aes cryptojs
source share
2 answers

This part of your code is incorrect:

 KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128/32); //->---------------------------------------------------------------------^^^^^^^ 

The value 128/32 erroneous. You need either 128 , 192 , or 256 . You currently have the equivalent of 4 , which does not seem to lead to exit the PBKDF2 function.

In addition, in Java, you must use DatatypeConverter.parseHexBinary() or the like to convert hex to bytes. You are currently just calling getBytes() , which is not true.

Finally, you need to specify CBC mode and PKCS # 5 to match your Javascript code. Therefore, change the line to:

 Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
+7
source share

Thanks to Duncan for the quick reply and advice. I give a complete solution that worked below for me in the interests of others.

Java code to decrypt an encrypted cryptojs message

 public static void main(String args[]) throws Exception{ String password = "Secret Passphrase"; String salt = "222f51f42e744981cf7ce4240eeffc3a"; String iv = "2b69947b95f3a4bb422d1475b7dc90ea"; String encrypted = "CQVXTPM2ecOuZk+9Oy7OyGJ1M6d9rW2D/00Bzn9lkkehNra65nRZUkiCgA3qlpzL"; byte[] saltBytes = hexStringToByteArray(salt); byte[] ivBytes = hexStringToByteArray(iv); IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); SecretKeySpec sKey = (SecretKeySpec) generateKeyFromPassword(password, saltBytes); System.out.println( decrypt( encrypted , sKey ,ivParameterSpec)); } public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException { KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); SecretKey secretKey = keyFactory.generateSecret(keySpec); return new SecretKeySpec(secretKey.getEncoded(), "AES"); } public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } public static String decrypt(String encryptedData, SecretKeySpec sKey, IvParameterSpec ivParameterSpec) throws Exception { Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, sKey, ivParameterSpec); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); return decryptedValue; } 
+6
source share

All Articles