Java 解密字符串会生成IllegalBlockSizeException
我在处理解密方法时遇到问题。加密产生正确的输出,但当我解密完全相同的加密字符串时(应该返回到纯文本字符串),它不起作用Java 解密字符串会生成IllegalBlockSizeException,java,encryption,cryptography,Java,Encryption,Cryptography,我在处理解密方法时遇到问题。加密产生正确的输出,但当我解密完全相同的加密字符串时(应该返回到纯文本字符串),它不起作用 import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class Samp { private static String IV = "aaaaaaaaaaaaaaaa"; pri
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Samp {
private static String IV = "aaaaaaaaaaaaaaaa";
private static final String UNICODE_FORMAT = "UTF8";
private String padd(String plaintext) {
while (plaintext.length() % 16 != 0) {
plaintext += "\0";
}
return plaintext;
}
public String encryptString(String plaintext, String encryptionKey) {
try {
byte[] cipher = encrypt(padd(plaintext), encryptionKey);
return new String(cipher, UNICODE_FORMAT);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public String decryptString(String encString, String encryptionKey) {
try {
System.out.println("**** decryptString ****");
System.out.println("enc = " + encString);
System.out.println("key = " + encryptionKey);
String decrypted = decrypt(encString.getBytes(UNICODE_FORMAT), encryptionKey);
return decrypted;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(UNICODE_FORMAT), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes(UNICODE_FORMAT)));
return cipher.doFinal(plainText.getBytes(UNICODE_FORMAT));
}
private static String decrypt(byte[] cipherText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(UNICODE_FORMAT), "AES");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV.getBytes(UNICODE_FORMAT)));
return new String(cipher.doFinal(cipherText), UNICODE_FORMAT);
}
// implement methods here
// using AES simple encryption
public static void main(String[] args){
String plaintext = "Hello World!";
String key = "asdfqaqwsaerdqsw";
Samp s = new Samp();
String enc = s.encryptString(plaintext, key);
System.out.println("encrypted string = " + enc);
String dec = s.decryptString(enc, key);
System.out.println("decrypted string = " + dec);
}
}
我已经看过了,它和我的问题一样。我遵循了建议(更改getBytes()->getBytes(UNICODE_格式)),但仍然是一样的。我仍然得到一个异常(javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数)这是我的代码
public static String encrypt(String data) throws Exception {
SecretKeySpec key = generateKey();
final Cipher c = Cipher.getInstance("AES/EAX/NoPadding", "BC");
c.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encVal = c.doFinal(data.getBytes("UTF8"));
String encryptedValue = Hex.toHexString(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
final Cipher c = Cipher.getInstance("AES/EAX/NoPadding", "BC");
c.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] ba = Hex.decode(encryptedData);
byte[] encVal = c.doFinal(ba);
return new String (encVal);
}
这是我的代码
public static String encrypt(String data) throws Exception {
SecretKeySpec key = generateKey();
final Cipher c = Cipher.getInstance("AES/EAX/NoPadding", "BC");
c.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encVal = c.doFinal(data.getBytes("UTF8"));
String encryptedValue = Hex.toHexString(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
final Cipher c = Cipher.getInstance("AES/EAX/NoPadding", "BC");
c.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] ba = Hex.decode(encryptedData);
byte[] encVal = c.doFinal(ba);
return new String (encVal);
}
您应该使用字符和字节之间1对1映射的编码,例如“ISO-8859-1”。所以把你的代码改成
private static final String UNICODE_FORMAT = "ISO-8859-1";
解决了这个问题。您应该使用字符和字节之间1:1映射的编码,例如“ISO-8859-1”。所以把你的代码改成
private static final String UNICODE_FORMAT = "ISO-8859-1";
public String encryptString(String plaintext, String encryptionKey)
解决了这个问题
public String encryptString(String plaintext, String encryptionKey)
问题就在这里。字符串不是二进制数据的容器。此方法应返回一个字节[]。类似地,decrypt()方法应该将byte[]作为密文参数,而不是字符串
问题就在这里。字符串不是二进制数据的容器。此方法应返回一个字节[]。类似地,decrypt()方法应该将byte[]作为密文参数,而不是字符串。如果使用
NoPadding
算法,为什么要在padd
中填充到16个字节,如果我不填充,那么效果不好,所以我决定填充纯文本,它起作用了注意,用零字符填充是不明确的:在解密时,没有办法分辨尾随的零是原始字符串的一部分还是填充的一部分。是的,我也注意到了这一点。您认为@JeffreyHantin的建议是明确的:填充由n个尾随字节组成,所有值均为n。如果您使用的是NoPadding
算法,为什么要在padd
中填充到16个字节,如果我不填充,则效果不好,所以我决定填充纯文本,它起作用了注意,用零字符填充是不明确的:在解密时,没有办法分辨尾随的零是原始字符串的一部分还是填充的一部分。是的,我也注意到了这一点。您认为@JeffreyHantin的建议是明确的:填充由n个尾随字节组成,所有值均为n.nice!!它解决了问题,但如何解决?你能解释一下吗?用纯文本来表示加密的数据是完全错误的。加密数据可以并将包含0到255之间的所有字节值,这些字节值并非都是可打印字符。您必须使用十六进制或Base64编码,而不是简单地将字节数组转换为字符串。@OlegEstekhin感谢您指出这一点。OP无论如何都会这么做,我无意改变他处理加密数据的方式。出于学习或练习的目的,我认为这没关系。@krato您需要1对1映射编码,因此encString.getBytes(UNICODE\u格式)
为您提供正确的密码nice!!它解决了问题,但如何解决?你能解释一下吗?用纯文本来表示加密的数据是完全错误的。加密数据可以并将包含0到255之间的所有字节值,这些字节值并非都是可打印字符。您必须使用十六进制或Base64编码,而不是简单地将字节数组转换为字符串。@OlegEstekhin感谢您指出这一点。OP无论如何都会这么做,我无意改变他处理加密数据的方式。出于学习或练习的目的,我认为这是可以的。@krato您需要1对1映射编码,因此encString.getBytes(UNICODE\u格式)
为您提供正确的cipher@ScaryWombat或者不对字节进行编码,完全消除出现问题的机会,并通过以后不知情的修补完全防止问题再次发生,首先正确地设计方法签名。@ScaryWombat或don't encoded the bytes,并完全消除问题发生的机会,然后通过在第一位置正确地设计方法签名,通过不知情的修补完全防止问题再次发生。