如何在java服务器端解密cryptojs AES加密消息?

我有以下基于cryptojs的javascript加密/解密函数,它们运行得非常好。

我使用随机盐,随机iv值和特定密码,同时使用cryptpjs加密消息。 我重复使用相同的salt,iv和密码来生成密钥,同时解密加密的消息。

这部分效果很好..

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); } 

但是当我尝试在java服务器端解密相同的加密文本时,问题就出现了。 我希望我的java服务器代码解密加密的消息。 这是我写的Java代码:

 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; } 

但我得到以下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.(SecretKeySpec.java:96) 

我不知道该怎么做

这部分代码是错误的:

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

128/32值是错误的。 您需要192256 。 目前你有相当于4 ,这似乎导致PBKDF2函数没有输出。

此外,在Java中,您应该使用DatatypeConverter.parseHexBinary()或类似的方法将hex转换为字节。 目前你只是调用getBytes()这是不对的。

最后,您需要指定CBC模式和PKCS#5填充以匹配您的Javascript代码。 所以将行改为:

 Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

感谢Duncan的迅速回应和建议。 我正在提供对我有用的完整解决方案,以造福他人。

用于解密cryptojs加密消息的Java代码

 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; }