首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无效的AES密钥长度: 20字节(Java 11)

无效的AES密钥长度: 20字节(Java 11)
EN

Stack Overflow用户
提问于 2022-11-10 09:39:32
回答 1查看 53关注 0票数 1

我正在尝试使用Java生成一个密钥。老实说,我在密钥、密码、密码和加密方面没有那么丰富的经验。

不管我从这个网站上搜索了什么,我都认为这是一个很常见的问题。我做了一些阅读,并想出了我写的代码:

代码语言:javascript
运行
复制
    Security.setProperty("crypto.policy", "unlimited");

    String valueToEncode = "some_random_text";

    SecureRandom secureRandom = new SecureRandom();
    byte[] salt = new byte[256];

    secureRandom.nextBytes(salt);

    KeySpec keySpec = new PBEKeySpec("some_random_password".toCharArray(), salt, 65536, 256); // AES-256
    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHHMACSHA512ANDAES_256");
    byte[] key = secretKeyFactory.generateSecret(keySpec).getEncoded();
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    byte[] ivBytes = new byte[16];

    secureRandom.nextBytes(ivBytes);

    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

    byte[] encValue = cipher.doFinal(valueToEncode.getBytes(StandardCharsets.UTF_8));
    byte[] finalCiphertext = new byte[encValue.length + 2 * 16];

    System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
    System.arraycopy(salt, 0, finalCiphertext, 16, 16);
    System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);

    System.out.println(finalCiphertext.toString());

这是根据我在另一篇文章中看到的答案而修改的。但我仍然得到“无效长度”错误。

我得到的错误是:

代码语言:javascript
运行
复制
Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 20 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 com.att.logicalprovisioning.simulators.Trial.main(Trial.java:47)

Trial.java:47是行:cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

有没有一种适合所有解决方案的方法?还是因为我缺乏理解?

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-10 11:08:33

您的密钥有20个字节长,因为secretKeyFactory.generateSecret(keySpec).getEncoded()返回密码some_random_password

修复代码的一个简单方法是使用键派生PBKDF2WithHmacSHA512而不是PBEWITHHMACSHA512ANDAES_256。这将根据密码和salt生成指定长度的密钥:

代码语言:javascript
运行
复制
...
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
...

然而,PBEWITHHMACSHA512ANDAES_256也可以应用。该算法使用PBKDF2WithHmacSHA512和随后的AES加密指定密钥派生。该实现在功能上与您的实现相同,但需要对代码进行更多的更改:

代码语言:javascript
运行
复制
...
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 65536, ivParameterSpec);

PBEKeySpec keySpec = new PBEKeySpec("some_random_password".toCharArray());
SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWITHHMACSHA512ANDAES_256");
SecretKey secretKey = kf.generateSecret(keySpec);       

Cipher cipher = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_256");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] encValue = cipher.doFinal(valueToEncode.getBytes(StandardCharsets.UTF_8));
...

另外两个问题是:

  • 您使用的是256个字节的盐,但连接时只存储16个字节。为了与级联保持一致,应用16字节盐:byte[] salt = new byte[16].
  • The output finalCiphertext.toString()只返回对象s. here的类和十六进制哈希码。对于有意义的输出,可以使用Base64或byte[]的十六进制编码,例如:byte[]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74386927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档