【问题标题】:AES-128-CBC cipher in javajava中的AES-128-CBC密码
【发布时间】:2020-06-24 19:09:32
【问题描述】:

我正在尝试使用 AES/128/CBC 实现加密,但我需要使用 64 字节密钥进行加密,但长度有问题。

是否可以使用 64 字节密钥加密 AES/128/CBC,因为我在 php 中使用 64 字节密钥的密码算法并且它可以工作,但在 java 中不行。

这是加密代码:

 public static String ALGORITHM = "AES";

 public static String AES_CBC_PADDING = "AES/CBC/PKCS5Padding";

 public static byte[] encrypt(final byte[] key, final byte[] IV, final byte[] message) throws Exception {
  return AESManager.encryptDecrypt(Cipher.ENCRYPT_MODE, key, IV, message);
 }

 public static byte[] decrypt(final byte[] key, final byte[] IV, final byte[] message) throws Exception {
  return AESManager.encryptDecrypt(Cipher.DECRYPT_MODE, key, IV, message);
 }

 private static byte[] encryptDecrypt(final int mode, final byte[] key, 
                                    final byte[] IV, final byte[] message) throws Exception {
  final Cipher cipher = Cipher.getInstance(AES_CBC_PADDING);
  final SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
  final IvParameterSpec ivSpec = new IvParameterSpec(IV);
  cipher.init(mode, keySpec, ivSpec);
  return cipher.doFinal(message);
 }

 public static String getHex(byte[] data, int length) {
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < length; i++) {
   String hexStr = Integer.toHexString(((int) data[i]) & 0xFF);
   if (hexStr.length() < 2) {
    sb.append("0").append(hexStr.toUpperCase());
   } else {
    sb.append(hexStr.toUpperCase());
   }
  }
  return sb.toString();
 }

我有这个错误:

java.security.InvalidKeyException: Invalid AES key length: 64 bytes
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:93)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:591)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:346)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:863)
at javax.crypto.Cipher.init(Cipher.java:1395)
at javax.crypto.Cipher.init(Cipher.java:1326)
at ec.otecel.tuenti.balance.util.AESManager.encryptDecrypt(AESManager.java)
at ec.otecel.tuenti.balance.util.AESManager.encrypt(AESManager.java)
at ec.otecel.tuenti.balance.util.FreemiumUtil.ciphertoFreemium(FreemiumUtil.java)
at ec.otecel.tuenti.balance.util.FreemiumUtil.main(FreemiumUtil.java)

我在 C:\Program Files\Java\jdk1.8.0_241\jre\lib\security 中有 local_policy.jar 和 US_export_policy.jar 那么,可能是什么问题?

【问题讨论】:

  • 我在 php 中有一个 64 字节密钥的密码算法,它可以工作......我在你的问题中没有看到任何 php 代码,甚至没有提示它在做什么.

标签: java encryption cypher aes cbc-mode


【解决方案1】:

AES-128 需要一个 16 字节的密钥。 “AES-128”中的“128”是以位为单位的密钥大小。除以 8 得到以字节为单位的密钥大小 == 16 字节。

我在 php 中有一个 64 字节密钥的密码算法,它可以工作

我......持怀疑态度。我怀疑它以某种方式从 64 个字节派生了一个 16 个字节的密钥。

【讨论】:

  • 嗨,是的,它可以工作,但现在我尝试使用 32 secretdKey 长度并且它可以工作但在 java 中不起作用,所以我在 php secretdKey 中将字符从位置 16 更改为 32 并且它继续工作,所以根据你说什么我得出结论,openssl_encrypt 根据方法 (128,256,512) 中继了 secretdKey,但我需要向安全团队找到有关它的文档。谢谢
【解决方案2】:

正如@dnault 所述,AES-128 的加密/解密密钥长度为 16 个字节(AES-192 = 24 个字节,AES-256 = 32 个字节)。您写道,您正在为 PHP 中的解密方法提供一个 64 字符长的密钥。我的示例程序显示只使用了密钥的前 16 个字符。

Java 应用解决方案:只需使用“密钥”的前 16 个字节(从左侧看)进行加密和解密:

<?php
    // https://stackoverflow.com/questions/62562417/aes-128-cbc-cipher-in-java/62562813#62562813
    $method = "AES-128-CBC";
    $plaintext = "Hello World";
    $key = "1234567890123456789012345678901234567890123456789012345678901234";
    var_dump($key);
    $iv =  "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
    $encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv));
    echo 'encrypted with key ' . $key . ' is ' . $encrypted . '<br>'. PHP_EOL;
    // truncated key = first 16 characters as for aes-128-cbc
    $key = "1234567890123456";
    var_dump($key);
    $encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv));
    echo 'encrypted with key ' . $key . ' is ' . $encrypted . '<br>'. PHP_EOL;
?>

结果:

string(64) "1234567890123456789012345678901234567890123456789012345678901234"
encrypted with key 1234567890123456789012345678901234567890123456789012345678901234 is iLaK2e4sWLOb0KfGy7ZRsQ==<br>
string(16) "1234567890123456"
encrypted with key 1234567890123456                                                 is iLaK2e4sWLOb0KfGy7ZRsQ==<br>

【讨论】:

  • 是的,openssl_encrypt 函数在内部对 16 位密钥执行中继,我发现它: 重要提示:密钥的长度应与您使用的密码完全相同。例如,如果您使用 AES-256,那么您应该提供一个 32 字节长(256 位 == 32 字节)的 $key。 $key 中的任何额外字节都将被截断并且根本不使用。来自:php.net/manual/es/function.openssl-encrypt.php#121818
猜你喜欢
  • 2013-08-11
  • 2018-04-04
  • 2021-06-25
  • 1970-01-01
  • 2019-08-17
  • 2020-04-15
  • 2017-03-27
  • 1970-01-01
  • 2020-10-06
相关资源
最近更新 更多