当前位置: 首页 > 面试题库 >

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

寇丰
2023-03-14
问题内容

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

在使用cryptpjs加密消息时,我使用随机盐,随机iv值和特定密码。在解密加密的消息时,我重复使用了相同的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 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)

我不知道该怎么办


问题答案:

您的代码的这一部分是错误的:

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

128/32值是错误的。您需要用128192256。当前,您具有的等价物4,这似乎导致PBKDF2函数完全没有输出。

另外,在Java中,您应该使用DatatypeConverter.parseHexBinary()或类似的将十六进制转换为字节。目前,您正在拨打getBytes()不正确的电话。

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

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


 类似资料:
  • 我正在尝试使用在我的设备上生成的RSA密钥解密我的android应用程序中的字符串。加密由php服务完成,使用我的应用程序提供的公共rsa密钥。我的问题是解密,解密失败了。 我正在做以下工作: 在用base64.encode(pubkey.getencoded())和私钥进行“base64”编码后,这两个密钥(公共和私有)都保存到文件中。->好 当我调用我的webservice时,我在post变量

  • 我必须用Twofish/CBC算法在Delphi中加密字符串,将其发送到服务器并在那里解密。我已经测试了下面的代码,B64编码/解码过程有效,但是我被困在密码加密/解密上。 我正在使用DEC 5.2用于德尔福。 以下是进行加密的德尔菲代码: 和应该解密发送数据的PHP函数: 我相信我必须对salt和初始化向量做更多的改动,但是我不知道怎么做。据我所知,KDFx()函数使SHA1从用户密码和salt

  • 服务器端加密是FDS在将您的数据写入数据中心的磁盘时会在对象级别上加密这些数据,并在您访问这些数据时为您解密这些数据。FDS加密使用AES-256来加密您的数据。 应用场景 适合对于数据存储有高安全性或者合规性要求的应用场景。 使用方式 在控制台开启bucket的加密存储 开启加密后,会对新上传的Object使用AES-256进行加密。若要对存量数据加密,请使用 存量数据加密工具 被加密的Obje

  • 问题内容: 我需要用openssl生成的和密钥替换从Unix到Java代码的加密和解密步骤 我生成密钥 我在Unix中使用键(我需要在Java中执行) 这是我的尝试 但它不起作用,PKCS8EncodedKeySpec / X509EncodedKeySpec不正确…但是我不知道该放什么 问题答案: 我认为您在读取PEM文件时遇到问题。JPA不直接支持PEM格式。您有两种选择,要么将它们转换为DE

  • 问题内容: 我编写的使用3DES在Java中对字符串进行编码的每种方法都无法解密回原始字符串。是否有人有一个简单的代码片段,可以对字符串进行编码,然后再将其解码回原始字符串? 我知道我在此代码中的某个地方犯了一个非常愚蠢的错误。到目前为止,这是我一直在努力的工作: 注意,我不是从crypto方法返回BASE64文本,也不是在解密方法中不是对base64进行未编码的,因为我试图查看我是否在BASE6

  • 在通常的场景中,连接字符串包含纯文本的密码,但这可以被Wireshark捕获,因此我想在一个连接字符串中使用加密的密码。我从Postgres文档中找到了以下摘录: