Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BouncyCastle Encrypt - Missing "END PGP MESSAGE"

We recently upgraded our BouncyCastle .jar files to use the latest available version, and have been working to implement them into our existing code.

In testing the encryption method, we've found that the file created lacks the "END PGP MESSAGE" end tag. And seems to also lack the trailing encryption lines to mark the signature.

This is our implementation of the signed output writer - are we missing an essential step to signing our file? Or is our implementation wrong?

public static void writeSignedOutputStream(PGPKeyPair keyPair, byte[] data, OutputStream outStream, char dataType, String fileName, boolean withArmor)
        throws IOException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException
    {
        try{
            registerProvider();

            if(withArmor)
                outStream = new ArmoredOutputStream(outStream);

            PGPPrivateKey privateKey = keyPair.getPrivateKey();
            PGPPublicKey publicKey = keyPair.getPublicKey();

            // Original signature generator
            //PGPSignatureGenerator generator = new PGPSignatureGenerator(publicKey.getAlgorithm(), PGPUtil.SHA1, provider.getName());
            PGPSignatureGenerator sigGenerator = 
                    new PGPSignatureGenerator(new BcPGPContentSignerBuilder(publicKey.getAlgorithm(), PGPUtil.SHA1));

            // Updating for new version of BouncyCastle 
            //generator.initSign(PGPSignature.BINARY_DOCUMENT, privateKey);
            sigGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey);

            for(Iterator i = publicKey.getUserIDs(); i.hasNext(); ){
                PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator();
                subpacketGenerator.setSignerUserID(false, (String)i.next());
                sigGenerator.setHashedSubpackets(subpacketGenerator.generate());
            }

            BCPGOutputStream bcpgStream = new BCPGOutputStream(outStream);

            sigGenerator.generateOnePassVersion(true).encode(bcpgStream);

            PGPLiteralDataGenerator dataGenerator = new PGPLiteralDataGenerator(false);
            OutputStream dataStream = dataGenerator.open(bcpgStream, dataType, fileName, data.length, new Date());

            for(int c = 0; c < data.length; c++){
                dataStream.write(data[c]);
                sigGenerator.update(data[c]);
            }

            sigGenerator.generate().encode(bcpgStream);
            dataStream.close();
            dataGenerator.close();
            bcpgStream.close();

        }catch(PGPException pe){
            //Exception catching
        }catch(Exception e){ 
            //Exception Catching
        }finally{}
    }

Here's what the output file looks like [with encrypted data censored] to give an illustration of the issue - I'm expecting to see "--END PGP MESSAGE--" at the bottom of this message, but it is simply not there.

Encrypted file - the expected "--END PGP MESSAGE--" text does not appear at the bottom

like image 312
Zibbobz Avatar asked Apr 30 '26 22:04

Zibbobz


2 Answers

I think you probably have issue because you don't flush your streams so some buffered data is not written.
Try to flush your output stream by calling outStream.flush() and bcpgStream.flush()

like image 64
Sergi Avatar answered May 02 '26 11:05

Sergi


So I'm encountering the exact same problem using 1.64, but with exporting a PublicKeyRing. I looked into how the footer gets written into an ArmoredOutputStream, and it only happens when close is called. In my case I was writing out using the encode method within a try / finally where close was in the finally. Something like the following:

PGPPublicKeyRing publicKeyRing = ...;

ByteArrayOutputStream out = new ByteArrayOutputStream();
ArmoredOutputStream aos = new ArmoredOutputStream( out );
try {
   publicKeyRing.encode( aos, true );
   aos.flush();
   return out.toByteArray();
} finally {
   aos.close();
}

The problem is that the footer isn't added until close is called, but since I was writing it to the ByteArrayOutputStream and retrieved the byte[] before close was called hence not getting the footer.

Rewriting it to this fixed the issue:

PGPPublicKeyRing publicKeyRing = ...;

ByteArrayOutputStream out = new ByteArrayOutputStream();
ArmoredOutputStream aos = new ArmoredOutputStream( out );
try {
   publicKeyRing.encode( aos, true );
   aos.flush();
} finally {
   aos.close();
}
return out.toByteArray();

Viola now I see the footer and the output is valid.

like image 34
chubbsondubs Avatar answered May 02 '26 11:05

chubbsondubs