Java 11中AES密钥长度无效(20字节)问题求助
问题:Java AES加密时出现「无效密钥长度」错误
我正在尝试使用Java生成密钥,本人对密钥、密码、密码算法及加密技术并不熟悉。通过查阅资料修改了一段代码后,仍遇到「无效密钥长度」错误。
代码示例
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());
错误信息
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)
错误发生在cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);行(对应Trial.java第47行),希望得到通用解决方案。
解决方案
错误核心原因
你使用的PBEWITHHMACSHA512ANDAES_256算法生成的SecretKey本身就是符合AES-256要求的密钥,但错误地调用getEncoded()后再用SecretKeySpec重新包装,导致密钥长度异常。该PBE算法生成的密钥内部已包含AES所需的正确长度密钥,无需额外转换。
修正后的代码
import java.security.SecureRandom; import java.security.Security; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; public class Trial { public static void main(String[] args) throws Exception { Security.setProperty("crypto.policy", "unlimited"); String valueToEncode = "some_random_text"; SecureRandom secureRandom = new SecureRandom(); byte[] salt = new byte[16]; // 盐值通用长度为16字节,无需256字节 secureRandom.nextBytes(salt); // 初始化PBE密钥规范 KeySpec keySpec = new PBEKeySpec("some_random_password".toCharArray(), salt, 65536, 256); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHHMACSHA512ANDAES_256"); // 直接使用生成的SecretKey,跳过不必要的SecretKeySpec转换 SecretKey secretKey = secretKeyFactory.generateSecret(keySpec); byte[] ivBytes = new byte[16]; secureRandom.nextBytes(ivBytes); IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); // 初始化Cipher时直接传入生成的SecretKey Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec); byte[] encValue = cipher.doFinal(valueToEncode.getBytes(java.nio.charset.StandardCharsets.UTF_8)); // 调整结果数组长度,匹配实际盐值长度 byte[] finalCiphertext = new byte[encValue.length + ivBytes.length + salt.length]; System.arraycopy(ivBytes, 0, finalCiphertext, 0, ivBytes.length); System.arraycopy(salt, 0, finalCiphertext, ivBytes.length, salt.length); System.arraycopy(encValue, 0, finalCiphertext, ivBytes.length + salt.length, encValue.length); // 使用Base64转换为可读字符串,避免打印内存地址 System.out.println(Base64.getEncoder().encodeToString(finalCiphertext)); } }
额外优化点
- 盐值长度调整:原代码定义256字节盐值但仅拷贝16字节到结果,改为通用的16字节盐值更合理。
- 加密结果输出:原代码直接打印
byte[]的toString()会输出内存地址,改用Base64编码可得到可读的加密字符串。 - 无限制加密策略:确保JDK已启用无限制加密策略(代码中已设置
crypto.policy为unlimited),否则AES-256会因权限限制无法使用。
内容的提问来源于stack exchange,提问作者hell_storm2004
相关产品推荐
相关产品推荐

