javasecurityencryptionzipoutputstream

Is the compression happening after the encryption?


While reviewing an encryption scheme, I came accross the following code:


    @Override
    public OutputStream encrypt(OutputStream outputStream) throws Exception {

        // generate the IV for encryption
        final byte[] encryptionIV = KeyFileUtil.randomBytes(16);
        outputStream.write(encryptionIV);

        // now create the encryption cipher
        final Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, getKey(), new GCMParameterSpec(128, encryptionIV));

        // The CipherOutputStream shouldn't close the underlying stream
        outputStream = new FilterOutputStream(outputStream) {
            @Override
            public void close() throws IOException {
                // Do nothing
            }
        };
        final CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);

        if (useZip) {
            final ZipOutputStream zipOutputStream = new ZipOutputStream(cos) {
                @Override
                public void finish() throws IOException {
                    super.finish();
                    def.end();
                }

                @Override
                public void flush() {
                    // Do nothing.
                }

                @Override
                public void close() throws IOException {
                    try {
                        super.flush();
                    } catch (final IOException exception) {
                        // Continue and try to close.
                    }
                    super.close();
                }
            };
            zipOutputStream.putNextEntry(new ZipEntry("ResourceContents"));
            return zipOutputStream;
        }
        return cos;
    }

As far as I understand the ordering of the streams is such that data is being encrypted first then (uselessly) compressed. Is this correct or am I misunderstanding how ordering works on OutputStreams?

Thanks


Solution

  • Yes, you're misunderstanding (or reading) how ordering works.

    At new ZipOutputStream(cos) the CipherOutputStream is wrapped by the ZOS, therefore data is first zipped, then passed on to the wrapped stream, which will encrypt the data, and then pass it on to the next wrapped stream, and so on.

    The outermost stream gets first go at the data, and if compression is enabled, return zipOutputStream; is called, with the zipstream being the outermost stream. It's idiomatic use of FilterOutputStream.