解密困难:错误是 BadPaddingException:给定的最终块未正确填充

Difficulty with Unencrypting: Error is BadPaddingException: Given final block not properly padded

正在尝试解密压缩文件。有些工作,有些则没有。那些不起作用的在尝试关闭 ZipInputStream 时会给出错误。

这在用户计算机上创建文件时工作正常,但我想避免这种安全风险。我以为我终于通过删除文件解决了所有风险,但目睹了文件没有被删除的情况。因此,我想完全避免这种可能性。使用 Using streams to decrypt and unzip to limit memory usage? 使我的代码达到这一点。

我已经阅读了几个关于填充等的地方,但我承认我继承了这段代码,但我仍在学习曲线上。

final File file = new File(path, fileName);
Key key = new SecretKeySpec(secret, "AES");
final Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
try (FileInputStream fis = new FileInputStream(file); CipherInputStream cis = new CipherInputStream(fis, cipher); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(cis))) {
                ZipEntry entry;
                while ((entry = zis.getNextEntry()) != null) {

                    List<String> lines;
                    try ( ByteArrayOutputStream output = new ByteArrayOutputStream(2048)) {
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            output.write(buffer, 0, len);
                        }
                        try (ByteArrayInputStream bais = new ByteArrayInputStream(output.toByteArray()); Reader reader = new InputStreamReader(bais)) {
                            lines = readFile(reader);
                        }
                    }
                    //Do something with lines of the file...

                }

            }

我得到的错误在下面,并在最后一行(try-with-resources 块的末尾)抛出。

java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded
    at javax.crypto.CipherInputStream.close(CipherInputStream.java:321)
    at java.io.BufferedInputStream.close(BufferedInputStream.java:472)
    at java.io.PushbackInputStream.close(PushbackInputStream.java:379)
    at java.util.zip.InflaterInputStream.close(InflaterInputStream.java:227)
    at java.util.zip.ZipInputStream.close(ZipInputStream.java:265)

Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:1970)
    at javax.crypto.CipherInputStream.close(CipherInputStream.java:314)

我已经调试并浏览了代码。抛出此错误的文件未加密并解压缩并正确读取。所有的数据都读出来了,"lines"各方面都完整了。它只是不关闭 ZipInputStream。有什么想法吗?

我的问题是我正在解密,但在尝试解压缩之前没有先重写到 ByteArrayOutputStream。

我的代码已更正并正常工作:

public void decrypt(final byte[] secret, final File encryptedFile ) throws IOException {
        final ByteArrayOutputStream baos;
        try {
            final Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, modelEncryptor.getKey());
            try (FileInputStream fis = new FileInputStream(encryptedFile); CipherInputStream cis = new CipherInputStream(fis, cipher)) {
                baos = new ByteArrayOutputStream();
                byte[] buff = new byte[8];
                int numRead = cis.read(buff);
                while (numRead != -1) {
                    baos.write(buff, 0, numRead); //I was trying to combine this write with the unzipping write.
                    numRead = cis.read(buff);
                }
            }
        } catch (Exception ex) {
            throw new IOException("Unable to decrypt " + encryptedFile, ex);
        }

        try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(bais))) {
            ZipEntry entry;
            while ((entry = zipIn.getNextEntry()) != null) {
                int BUFFER = 2048;
                ByteArrayOutputStream fos = new ByteArrayOutputStream(2048);
                try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER)) {
                    int count;
                    byte data[] = new byte[BUFFER];
                    while ((count = zipIn.read(data, 0, BUFFER)) != -1) {
                        dest.write(data, 0, count);
                    }
                    dest.flush();
                }
                final List<String> lines = Arrays.asList(fos.toString().split("\r\n"));
                //Do something with lines...
            }
        }
        baos.close();
    }

通过将解密与解压缩分开,现在一切正常。 希望有一天这对其他人有所帮助。

P.S。我在加密方面没有做任何改变。