使用aes / ecb / pkcs5padding解密字节数组时出现IllegalBlockSizeException

时间:2015-06-17 16:31:53

标签: java android encryption gradle aes

我知道aes加密需要以16块为单位,但我的印象是使用Cipher.getInstance("AES/ECB/PKCS5PADDING");填充字节数组来实现这一点。我的代码如下:

CipherUtils.java

private static byte[] key = {
        0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79
};//"thisIsASecretKey";

public static byte[] EncryptByteArray(byte[] array)
{
    try
    {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        return (cipher.doFinal(array));
    }
    catch (Exception e)
    {
      e.printStackTrace();

    }
    return null;
}

public static byte[] DecryptByteArray(byte[] array)
{
    try
    {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        return cipher.doFinal(array);
    }
    catch (Exception e)
    {
      e.printStackTrace();

    }
    return null;
}

主程序

        fis = new FileInputStream(path);

        toDecrypt = new byte[fis.available()+1];

        int content;
        int i = 0;
        while ((content = fis.read()) != -1) {

            // convert to byte and display it
            toDecrypt[i] = (byte)content;
            i += 1;
        }

        byte[] decryptedStr = CipherUtils.DecryptByteArray(toDecrypt);

        FileOutputStream decryptedStream = new FileOutputStream(path);
        decryptedStream.write (decryptedStr);
        decryptedStream.close();

path处的文件使用cipherutils.java中的函数加密,并使用FileOutputStream.write

写入文件

更新 - 我正在使用Gradle为Android构建。

2 个答案:

答案 0 :(得分:3)

这是问题所在:

toDecrypt = new byte[fis.available()+1];

首先,您使用的是available()方法,永远不会一个好主意。接下来,即使假设 返回文件的长度,你也要加1 - 为什么?你只需要文件中的字节。

最简单的方法就是使用Files.readAllBytes

byte[] toDecrypt = Files.readAllBytes(Paths.get(path));
// TODO: Change the method name to follow Java conventions
byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt);
Files.write(Paths.get(path), decrypted);

现在您不必担心关闭文件流,...(如果您设法解密,您可能无法写入,因为您仍然打开了文件阅读当前的代码。)

我还强烈建议您重新审视您的“处理”异常:

  • 抓住Exception几乎总是一个坏主意
  • 调用e.printStackTrace()然后继续,好像什么都没发生几乎总是一个坏主意

答案 1 :(得分:0)

使用@ JonSkeet的答案管理工作:谢谢!:

        File file = new File(path);
        fis = new FileInputStream(file);

        toDecrypt = new byte[(int)file.length()];
        fis.read(toDecrypt);

        byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt);
        FileOutputStream decryptedStream = new FileOutputStream(bookPath);
        decryptedStream.write (decrypted);
        decryptedStream.close();

正如他指出的那样,我不应该使用available()方法。还有一个更好的&写入文件的速度比迭代每个字节更快!根据评论,我还使用随机IV将加密更改为CBC模式。