3

我知道如果我正在创建和写入一个 zip 文件,我将 ZipOutputStream 包装在一个 OutputStream (或子类)周围,如下所示:

fos = new FileOutputStream(fileName)
zOut = new ZipOutputStream(fos);

我还知道如何创建一个 zip 文件以及需要指定何时添加新条目并关闭条目。我想做的是加密存档中的文件,但不加密存档,以便仍然很容易找到条目。(部分原因是因为不同的条目将在不同的时间被读取 - 如果我加密整个 zip 文件,那么我每次都必须从头开始读取它,即使我需要的 zip 条目是第 99 个。如果整个文件被加密,我将无法随机访问条目。)

我通常知道要加密(或解密),我将一个流包裹在另一个流周围,如下所示:

fos = new FileOutputStream("ciphertext");
CipherOutputStream cos = new CipherOutputStream(fos, key);

我假设如果我正在写入 ZipOutputStream 并且想要加密条目,以创建 ZipOutputStream,我可以执行我在第一个示例中所做的事情,然后当需要为 zip 条目写入数据时,我将 ZipOutputStream 包装在 CipherOutputStream 中,如下所示:

fos = new FileOutputStream(fileName)
zOut = new ZipOutputStream(fos);
...
CipherOutputStream cos = new CipherOutputStream(zOut, key);

但这提出了几个问题:

  1. 一般来说,对于这样的事情,流的顺序是否重要?如果我将 CipherOutputStream 包装在 ZipOutputStream 中,或者我可以反过来做吗?换句话说,如果整个文件都被加密了,哪个流包裹在哪个流周围有关系吗?
  2. 如果我按照上述方式进行操作,并对每个条目中的数据使用 CipherOutputScream,那么当我需要关闭该条目并继续下一个条目时该怎么办?我可以销毁 CipherOutputStream 而不影响它所包裹的流吗?
  3. 有没有更好的方法只加密 zip 条目而不加密 zip 文件中的目录和其他数据?
4

2 回答 2

3

不要与流混淆。有一个流可以在磁盘 ( ZipOutputStream) 上创建/更新存档文件。此流未编码,因此您必须单独保留此代码。

您想要的是加密各个条目的数据。因此,当您向存档添加新条目时,请putNextEntry()照常添加新条目。

现在加载要加密的数据并创建一个CipherOutputStream写入ByteArrayOutputStream. 以这种方式编码所有数据,然后将字节附加ByteArrayOutputStream到存档中:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

CipherOutputStream cos = new CipherOutputStream(buffer, key);
... encode data ...

byte[] data = buffer.toByteArray();
zOut.write( data, 0, data.length );

请注意,您可能希望使用来阅读存档,ZipFile因为它为InputStream您可以包装的每个条目提供了一个单独的条目。

于 2013-01-03T09:06:39.063 回答
0

我是新来的,因此我无法对 Aaron Digulla 的帖子发表评论。这是对他的职位的补充。

加密将数据冗余降至最低,因此加密后的压缩是无效的。压缩后的输出通常大于未压缩的输入。为防止更大的输出,请使用 0 压缩级别。仅当 zip 文件只是一个容器时,此解决方案才有效。

于 2017-01-15T10:46:59.780 回答