AES加密Java无效密钥长度

我正在尝试创建AES加密方法,但由于某种原因,我一直在努力

java.security.InvalidKeyException: Key length not 128/192/256 bits

这是代码:

 public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); // NOTE: last argument is the key length, and it is 256 KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); return(secret); } public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ SecretKey secret = getSecretKey(password, salt); Cipher cipher = Cipher.getInstance("AES"); // NOTE: This is where the Exception is being thrown cipher.init(Cipher.ENCRYPT_MODE, secret); byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); return(ciphertext); } 

谁能看到我做错了什么? 我认为它可能与SecretKeyFactory算法有关,但这是我能找到的唯一一个支持我正在开发的终端系统。 任何帮助,将不胜感激。 谢谢。

要获得更强大的密钥强度加密,您需要下载Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files。

http://java.sun.com/javase/downloads/index.jsp (查看其他下载内容)。

您可以按照其他几个类似问题的建议安装JCE Unlimited Strength jar,或者尝试在主函数或驱动程序中包含此代码。

 try { java.lang.reflect.Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); field.setAccessible(true); field.set(null, java.lang.Boolean.FALSE); } catch (Exception ex) { ex.printStackTrace(); } 

这里的问题是密钥派生函数的密钥大小与给定密码之间的不匹配。 您使用的PBKDF是"PBEWithMD5AndDES" ,在此字符串中, DES部分表示输出的类型。 因为已知的单个DES仅使用8字节密钥(64位,56个有效位大小和奇偶校验位)。 AES密钥应为128,192和256位,不应包含奇偶校验位。

要创建AES强度密钥大小,您至少应使用PBKDF2而不是PBKDF1,最好使用SHA-256或SHA-512来获得更高的密钥大小。 但是对于128位密钥,您应该使用SHA-1。 因此,请改用"PBKDF2WithHmacSHA1" SecretKeyFactory的内置版本。 请注意,键大于160位的PBKDF2 / SHA1将导致操作不理想。 如果要创建更多数据(例如单独的IV),您可能希望在输出上使用基于密钥的简单密钥派生函数(KBKDF)。

正如其他人所指出的,如果你使用超过128位的密钥,你将需要无限加密管辖权文件。


有关以下代码的说明:

  • 没有完整性保护,您甚至可能需要保护机密性
  • 使用零IV的CBC,这可能没问题,但只有当盐是完全随机的时(用密文存储盐)
  • 1024是PBKDF2的相对较少的迭代次数
  • PBKDF2与您使用的PBKDF1不兼容
 public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); // NOTE: last argument is the key length, and it is 128 KeySpec spec = new PBEKeySpec(password, salt, 1024, 128); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); return(secret); } public static byte[] encrypt(char[] password, byte[] salt, String text) throws GeneralSecurityException { SecretKey secret = getSecretKey(password, salt); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] ciphertext = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); return(ciphertext); } 

使用任何填充机制来填充空位

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

当我放置以下代码并运行它时,我没有收到任何例外:

 import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) { String pass = "this is the pass"; char[] pw = new char[pass.length()]; for(int k=0; k 

我从来没有能够重新创建你的例外。 我正在运行J2SE 1.6并在Eclipse上进行开发。

可能是你的密码长度不是16个字节?