-2

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

在用户计算机上创建文件时这工作正常,但我想避免这种安全风险。我以为我最终通过删除文件处理了所有风险,但目睹了文件未被删除的情况。因此,我想完全避免这种可能性。使用使用流来解密和解压缩以限制内存使用?让我的代码达到这一点。

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

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)

我已经调试并浏览了代码。引发此错误的文件未加密并解压缩并正确读取。所有数据都被读出,“行”在各个方面都是完整的。它只是不会关闭 ZipInputStream。有任何想法吗?

4

1 回答 1

1

我的问题是我正在解密,但在尝试解压缩之前没有先重写到 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();
    }

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

PS我在加密方面没有改变。

于 2016-06-08T18:49:26.527 回答