错误的原因是什么;java.security.InvalidKeyException:缺少参数“;?
我正在尝试使用AES加密和解密字符串,但遇到了一个错误,我不知道如何解决。代码如下:错误的原因是什么;java.security.InvalidKeyException:缺少参数“;?,java,aes,encryption,Java,Aes,Encryption,我正在尝试使用AES加密和解密字符串,但遇到了一个错误,我不知道如何解决。代码如下: public class EncryptionTest{ public static void main(String[] args) { String encrypt = new String(encrypt("1234567890123456")); System.out.println("decrypted value:" + (decrypt("ThisIsASecre
public class EncryptionTest{
public static void main(String[] args) {
String encrypt = new String(encrypt("1234567890123456"));
System.out.println("decrypted value:" + (decrypt("ThisIsASecretKey",encrypt)));
}
public static String encrypt(String value) {
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + (new String(encrypted)));
return new String(skeySpec.getEncoded());
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(Base64.decodeBase64(key), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(skeySpec.getEncoded(),"AES"));
(*)
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
original.toString();
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
当我运行它时,“描述”值为空。它在(***)之前失败
这给了我一个例外:
java.security.InvalidKeyException: Parameters missing
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:388)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:186)
at javax.crypto.Cipher.implInit(Cipher.java:787)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1213)
at javax.crypto.Cipher.init(Cipher.java:1153)
at firma.XmlEncryptionTest.decrypt(EncryptionTest.java:63)
at firma.XmlEncryptionTest.main(EncryptionTest.java:41)
java.security.InvalidKeyException:缺少参数
位于com.sun.crypto.provider.CipherCore.init(CipherCore.java:388)
位于com.sun.crypto.provider.aesciper.engineInit(aesciper.java:186)
位于javax.crypto.Cipher.implInit(Cipher.java:787)
在javax.crypto.Cipher.chooseProvider(Cipher.java:849)
位于javax.crypto.Cipher.init(Cipher.java:1213)
位于javax.crypto.Cipher.init(Cipher.java:1153)
在firma.XmlEncryptionTest.decrypt(EncryptionTest.java:63)
在firma.XmlEncryptionTest.main(EncryptionTest.java:41)
其中第63行是(***)前面的一行。我不知道我做错了什么,也不知道如何解决。我在互联网上四处查看,但没有找到丢失的参数可能是什么,代码中的主要问题是由于未能指定IV值而导致的。在执行CBC模式加密时必须指定IV值,并在执行CBC模式解密时使用相同的值 另一个问题是从字节数组和base64编码创建字符串的混合和匹配。每次从解密方法返回
null
。即使您的意思是返回original.toString()
,这仍然是错误的(因为toString()
在字节数组上做不到您希望的事情)
下面是代码的改进版本。这远不是最优的,但它可以编译并工作。您需要改进这一点,以使用随机IV。此外,如果您计划从密码派生密钥,而不仅仅是获取字节,请使用派生函数,如PBKDF2。您可以在中看到使用PBKDF2的示例
如果使用像CBC这样的块链接模式,那么还需要为密码提供IvParameterSpec
public class EncryptionTest {
static byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
static SecureRandom rnd = new SecureRandom();
static IvParameterSpec iv = new IvParameterSpec(rnd.generateSeed(16));
public static void main(String[] args) {
String encrypt = encrypt("1234567890123456");
System.out.println("decrypted value:" + (decrypt("ThisIsASecretKey", encrypt)));
}
public static String encrypt(String value) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + Base64.encodeBase64String(encrypted));
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec,iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}尽管为时已晚,但我仍在为其他人提供解决方案。请参阅下面的工作代码以加密和解密数据
public static byte[] encrypt(String value) {
byte[] encrypted = null;
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams);
encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + encrypted.length);
} catch (Exception ex) {
ex.printStackTrace();
}
return encrypted;
}
public static byte[] decrypt(byte[] encrypted) {
byte[] original = null;
Cipher cipher = null;
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
Key key = new SecretKeySpec(raw, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
byte[] ivByte = new byte[cipher.getBlockSize()];
//This class specifies an initialization vector (IV). Examples which use
//IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation.
IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec);
original= cipher.doFinal(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return original;
}
您正在为密码使用两个不同的init()。。。尝试使用相同的。是的,这部分
newsecretkeyspec(skeySpec.getEncoded(),“AES”)
看起来很奇怪-为什么不直接使用skeySpec
?@DuncanJones,如果我用“skeySpec”代替“newsecretkeyspec(skeySpec.getEncoded(),“AES”)”,我会得到一个新错误:无效的AES密钥长度:12字节,在同一行…@Shark我使用了相同的init()对于两个密码“cipher.init(cipher.DECRYPT_MODE,skeySpec);”我得到了一个例外:无效的AES密钥长度:12字节它不一样。。。查看是否创建了随机或零IV(如果有)取决于特定的JCE提供程序。明智的做法是不使用提供程序默认值,而是始终为需要的模式提供IV。出于同样的原因,您应该始终明确请求正确的分组密码模式和填充模式。您写道“在进行CBC模式加密时必须指定一个IV值,并在执行CBC模式解密时使用相同的值。”然后是“您需要改进以使用随机IV”。问题:如果我需要相同的IV进行解密,如何使用“随机”值?@user999999 IV不是一个敏感值,因此您通常使用密文存储/发送它。Hello@simpleuser,因为IV
需要匹配,那么一种方法是让每一方都有一个可能的IV
值列表,然后双方必须就一个索引达成一致,以决定使用哪个IV
。此索引必须在通信的初始握手期间进行通信。感谢您的解决方案!它起作用了,帮了我的忙:D
public static byte[] encrypt(String value) {
byte[] encrypted = null;
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams);
encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + encrypted.length);
} catch (Exception ex) {
ex.printStackTrace();
}
return encrypted;
}
public static byte[] decrypt(byte[] encrypted) {
byte[] original = null;
Cipher cipher = null;
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
Key key = new SecretKeySpec(raw, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
byte[] ivByte = new byte[cipher.getBlockSize()];
//This class specifies an initialization vector (IV). Examples which use
//IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation.
IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec);
original= cipher.doFinal(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return original;
}