【问题标题】:How can I force a CipherOutputStream to finish encrypting but leave the underlying stream open?如何强制 CipherOutputStream 完成加密但保持底层流打开?
【发布时间】:2011-07-23 21:00:33
【问题描述】:

我有一个由另一个 OutputStream 支持的 CipherOutputStream。将需要加密的所有数据写入 CipherOutputStream 后,我需要附加一些未加密的数据。

The documentation for CipherOutputStream 表示调用flush() 不会强制最后一个块退出加密器;为此,我需要致电close()。但是close() 也关闭了底层的OutputStream,我还需要写更多。

如何在不关闭流的情况下强制最后一个块退出加密器?我需要编写自己的 NonClosingCipherOutputStream 吗?

【问题讨论】:

    标签: java outputstream encryption


    【解决方案1】:

    如果您没有对Cipher 的引用,您可以将FilterOutputStream 传递给创建CipherOutputStream 的方法。在FilterOutputStream 中,覆盖close 方法,使其实际上不会关闭流。

    【讨论】:

    • 我会使用这个答案作为创建类似 NonClosingCipherOutputStream 的基础,但受到DigestOutputStream.on(...) 示例的启发,我将创建一个cipherFinish() 方法,之后流只需将数据传递到底层操作系统。
    【解决方案2】:

    也许你可以在放入密码输出流之前包装你的输出流

    /**
     * Represents an {@code OutputStream} that does not close the underlying output stream on a call to {@link #close()}.
     * This may be useful for encapsulating an {@code OutputStream} into other output streams that does not have to be
     * closed, while closing the outer streams or reader.
     */
    public class NotClosingOutputStream extends OutputStream {
    
        /** The underlying output stream. */
        private final OutputStream out;
    
        /**
         * Creates a new output stream that does not close the given output stream on a call to {@link #close()}.
         * 
         * @param out
         *            the output stream
         */
        public NotClosingOutputStream(final OutputStream out) {
            this.out = out;
        }
    
        /*
         * DELEGATION TO OUTPUT STREAM
         */
    
        @Override
        public void close() throws IOException {
            // do nothing here, since we don't want to close the underlying input stream
        }
    
        @Override
        public void write(final int b) throws IOException {
            out.write(b);
        }
    
        @Override
        public void write(final byte[] b) throws IOException {
            out.write(b);
        }
    
        @Override
        public void write(final byte[] b, final int off, final int len) throws IOException {
            out.write(b, off, len);
        }
    
        @Override
        public void flush() throws IOException {
            out.flush();
        }
    }
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      如果您有对 CipherOutputStream 包装的 Cipher 对象的引用,您应该能够执行 CipherOutputStream.close() 所做的事情:

      调用Cipher.doFinal,然后调用flush() CiperOutputStream,然后继续。

      【讨论】:

      • 所以我最初投了赞成票,因为这似乎是个好主意,但事实并非如此。 cipher.doFinal() 一遍又一遍地返回相同的字节,所以如果你手动将它们插入输出流,然后写更多的东西,最终关闭 CipherOutputStream,它们会再次插入。
      猜你喜欢
      • 2011-05-26
      • 2013-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 2015-09-21
      相关资源
      最近更新 更多