我正在尝试加密/解密文件中的文本但我收到以下错误:
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
我正在使用带有AES / ECB / PKCS5Padding的AES 128位。知道我为什么会收到这个错误吗? 这是我的代码:
public class AES_Encryption {
public static void main(String[] args) throws Exception {
String str = new Scanner(new File("src//plainText.txt")).useDelimiter("\\Z").next();
FileWriter fstream = new FileWriter("src//cipherText.txt");
BufferedWriter out = new BufferedWriter(fstream);
FileWriter fstream2 = new FileWriter("src//decrpytedText.txt");
BufferedWriter out2 = new BufferedWriter(fstream2);
System.out.println("" + str);
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
Key key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(str.getBytes());
String ct = new String(cipherText);
System.out.println( new String(cipherText, "UTF8") );
out.append(ct);
out.close();
String cipherT = new Scanner(new File("src//cipherText.txt")).useDelimiter("\\Z").next();
cipher.init(Cipher.DECRYPT_MODE, key);
//byte[] decVal = Base64.decode(cipherT.getBytes());
byte[] newPlainText = cipher.doFinal(cipherT.getBytes());
String dt = new String(newPlainText, "UTF8");
out2.append(dt);
out2.close();
}
}
答案 0 :(得分:3)
您的错误是将密文视为字符串:
String ct = new String(cipherText); // <--- Noooo!
字节数组中的值不能表示为默认字符集中的字符。
始终将密文视为字节数组,即使在读取或写入文件时也是如此。
答案 1 :(得分:1)
在Cipher API documentaion中提到的以下情况下获得IllegalBlockSizeException:
IllegalBlockSizeException - 如果此密码是块密码,则未请求填充(仅在加密模式下),以及数据的总输入长度 由此密码处理的不是块大小的倍数
在您的情况下,您正在正确加密字符串,但在解密时,您将cipherText视为String
然后
您将cipherT.getBytes()
字节数组放在doFinal
Cipher
方法中。 String的字节数组转换与以二进制模式从文件读取字节数组不同。
String API documentaion中提到的String.toBytes()
的功能和限制如下:
使用平台的默认字符集将此String编码为字节序列,并将结果存储到新的字节数组中。该 当此字符串无法编码时此方法的行为 默认字符集未指定。 CharsetEncoder类应该是 在需要更多控制编码过程时使用。
我建议您阅读二进制模式下的cipherText.txt
File
,然后在doFinal
Cipher
方法中读取文件后输入的字节数组。我已按以下方式修改了您的代码:
public class AES_Encryption {
public static void main(String[] args) throws Exception {
String str = new Scanner(new File("plainText.txt")).useDelimiter("\\t").next();
FileOutputStream fstream = new FileOutputStream("cipherText.txt");
BufferedOutputStream out = new BufferedOutputStream(fstream);
FileOutputStream fstream2 = new FileOutputStream("decrpytedText.txt");
BufferedOutputStream out2 = new BufferedOutputStream(fstream2);
System.out.println("INPUT String:\n" + str);
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
Key key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(str.getBytes());
System.out.println("ENCRYPTED String:\n"+new String(cipherText, "UTF8") );
out.write(cipherText);
out.flush();
out.close();
//String cipherT = new Scanner(new File("cipherText.txt")).nextLine();
BufferedInputStream bfin = new BufferedInputStream(new FileInputStream(new File("cipherText.txt")));//To read the file in Binary Mode.
cipher.init(Cipher.DECRYPT_MODE, key);
int BUFFERSIZE = 1024;
byte[] readBytes = new byte[BUFFERSIZE];
byte[] data = null;
int totalRead = -1;
while( (totalRead = bfin.read(readBytes))!=-1)
{
byte[] temp = new byte[(data == null ? totalRead : data.length)];
System.arraycopy((data==null ? readBytes : data),0,temp,0, temp.length);
data = new byte[(data == null ? 0 : data.length) + totalRead];
System.arraycopy(temp, 0, data, 0, temp.length);
System.arraycopy(readBytes, 0, data, data.length - temp.length, totalRead);
}
if (data!=null)
{
byte[] newPlainText = cipher.doFinal(data);
out2.write(newPlainText);
out2.flush();
System.out.println("DECRYPTED String:\n"+new String(newPlainText,"UTF8"));
}
else
{
System.out.println("No Data Found");
}
//String dt = new String(newPlainText, "UTF8");
out2.close();
}
}
我希望这可以帮助你解决你得到的异常......