简体   繁体   English

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

[英]How to decrypt a cryptojs AES encrypted message at the java server side?

I have the following cryptojs based javascript encryption/decryption functions which works perfectly fine. 我有以下基于cryptojs的javascript加密/解密函数,它们工作得很好。

I use a random salt, random iv value and a specific password while encrypting the message using cryptpjs. 我使用随机盐,随机iv值和特定密码,同时使用cryptpjs加密消息。 I reuse the same salt, iv and the password to generate the key while decrypting the encrypted message. 我重复使用相同的salt,iv和密码来生成密钥,同时解密加密的消息。

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 issue starts when I try to decrypt the same encrypted text at the java server side. 但是当我尝试在java服务器端解密相同的加密文本时,问题就出现了。 I want the encrypted message to be decrypted by my java server code. 我希望我的java服务器代码解密加密的消息。 Here is the Java code that I wrote: 这是我写的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;
}

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 I should do 我不知道该怎么做

Thanks to Duncan for the prompt response and advice. 感谢Duncan的迅速回应和建议。 I am giving the complete solution that worked for me below for the benefit of others. 我正在给出对我有用的完整解决方案,以造福他人。

Java code to do the decryption of the cryptojs encrypted message 用于解密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;
}

This part of your code is wrong: 这部分代码是错误的:

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

The 128/32 value is erroneous. 128/32值是错误的。 You need either 128 , 192 or 256 . 您需要用128192256 Currently you have the equivalent of 4 , which seems to result in no output at all from the PBKDF2 function. 目前你有相当于4 ,这似乎导致PBKDF2函数没有输出。

Also, in Java you should use DatatypeConverter.parseHexBinary() , or similar, to convert hex into bytes. 此外,在Java中,您应该使用DatatypeConverter.parseHexBinary()或类似的方法将十六进制转换为字节。 Currently you are just calling getBytes() which isn't right. 目前你只是调用getBytes()这是不对的。

Finally, you need to specify CBC mode and PKCS#5 padding in order to match your Javascript code. 最后,您需要指定CBC模式和PKCS#5填充以匹配您的Javascript代码。 So change the line to: 所以将行改为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM