2

我正在尝试加密/解密文件中的文本,但收到以下错误:

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();
}

}

4

2 回答 2

3

您的错误是将密文视为字符串:

String ct = new String(cipherText); // <--- Noooo!

字节数组中的某些值不能以默认字符集中的字符表示。

始终将您的密文视为字节数组,即使在读取或写入文件时也是如此。

于 2013-01-31T11:58:14.797 回答
1

如Cipher API 文档中所述,在以下情况下获得 IllegalBlockSizeException :

IllegalBlockSizeException - 如果此密码是块密码,则未请求填充(仅在加密模式下),并且此密码处理的数据的总输入长度不是块大小的倍数

在您的情况下,您正在正确加密字符串,但是在解密时您将 cipherText 视为String,然后将cipherT.getBytes()字节数组放入doFinal方法中Cipher。String 的字节数组转换不同于以二进制方式从文件中读取字节数组。String API 文档String.toBytes()中提到的功能和限制如下:

使用平台的默认字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。当此字符串无法以默认字符集编码时,此方法的行为未指定。当需要对编码过程进行更多控制时,应使用 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();
}
}

我希望这可以帮助您解决遇到的异常...

于 2013-01-31T17:24:52.807 回答