Flush PGP Encrypted Bouncy Castle OutputStream in Java

天涯浪子 提交于 2019-12-24 10:29:49

问题


I'm working on a proof of concept Java application that reads a series of newline-separated requests from a PGP-encrypted file, processes those requests, and then writes the responses to another PGP-encrypted file, with a flush after each response write.

I've successfully integrated Bouncy Castle 1.5 with my application with the exception that I cannot seem to flush the output on command:

private ArmoredOutputStream armoredOut = null;
private OutputStream compressedOut = null;
private OutputStream encryptedOut = null;

public OutputStream encryptStream(OutputStream outputStream){
    OutputStream literalOut = null;
    try{
        armoredOut = new ArmoredOutputStream(outputStream);
        BcPGPDataEncryptorBuilder dataEncryptor = new BcPGPDataEncryptorBuilder(PGPEncryptedData.AES_256);
        dataEncryptor.setSecureRandom(new SecureRandom());
        PGPEncryptedDataGenerator encryptGen = new PGPEncryptedDataGenerator(dataEncryptor);

        PGPPublicKey publicKey = null;
        InputStream publicKeyStream = null;
        try{
            publicKeyStream = this.getClass().getClassLoader().getResourceAsStream(keyName);
            publicKey = getEncryptionKey(publicKeyStream);
        }
        finally{
            if(publicKeyStream != null){
                publicKeyStream.close();
            }
        }
        if(publicKey == null){
            throw new IllegalArgumentException("Couldn't obtain public key.");
        }

        encryptGen.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));

        encryptedOut = encryptGen.open(armoredOut, new byte[bufferSize]);

        PGPCompressedDataGenerator compressGen = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
        compressedOut = compressGen.open(encryptedOut);

        PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
        literalOut = literalGen.open(compressedOut, PGPLiteralDataGenerator.UTF8, "Response", new Date(), new byte[bufferSize]);
    }
    catch(PGPException e){
        LOGGER.error(ExceptionUtils.getStackTrace(e));
    }
    catch(IOException e){
        LOGGER.error(ExceptionUtils.getStackTrace(e));
    }
    return literalOut;
}

The returned OutputStream does not flush when I explicitly call flush(). Only when the close() method is called on each of the compressedOut, encryptedOut, and armoredOut OutputStreams are they actually flushed.

I've tried to modify the Bouncy Castle source code, but everything I do leads to some sort of malformed or corrupted PGP message that cannot be decrypted. I've also tried to modify the buffer size to make it smaller, larger, and the exact size of a single request, but this didn't work.

Does anyone have any suggestions on how to manually flush an encrypted OutputStream with Bouncy Castle?


回答1:


I had the same problem with BC. Look into the ArmoredOutputStream class. Flush is empty and close doesn't call it's underlying outputstreams close. That means if you're working with ArmoredOutputStream or ArmoredInputStream you have to close ArmoredOutputStream itself AND the underlying Outputstream. The same for flush!



来源:https://stackoverflow.com/questions/28705211/flush-pgp-encrypted-bouncy-castle-outputstream-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!