bc-java icon indicating copy to clipboard operation
bc-java copied to clipboard

Change in encrypted cipher (after 1.80) !

Open Muthu-Palaniyappan-OL opened this issue 1 month ago • 3 comments

    String staticVector = "lbsTNi0WXIg=";
    String password = "HJQScqUp1l3zfy27RA4dvAE251WW2T+rKb7JQOXgvMQB7hCl/VFQE3WXyAL4PYRmIo8gK/kqQu/UykAiThrDYOVynrUED0Cg==KiT2on42Kp";
    String inputTextMsg = "Hi";

    SecureRandom consistentSecureRandom = new ConsistentByteProvider(Base64.decodeBase64(staticVector));
    JcePGPDataEncryptorBuilder builder = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5);
    builder.setWithIntegrityPacket(false);
    builder.setSecureRandom(consistentSecureRandom);
    PGPEncryptedDataGenerator generator = new PGPEncryptedDataGenerator(builder);
    generator.setForceSessionKey(false);
    JcePBEKeyEncryptionMethodGenerator method = new JcePBEKeyEncryptionMethodGenerator(
        password.toCharArray(), 
        1
    );
    method.setSecureRandom(consistentSecureRandom);
    generator.addMethod(method);
    ByteArrayOutputStream encOut = new ByteArrayOutputStream();
    OutputStream cOut = generator.open(encOut, new byte[1024]);

    cOut.write(inputTextMsg.getBytes());
    cOut.close();

    byte[] encrypted = encOut.toByteArray();

After bouncycastle 1.80, i believe we changed the way we generate OPENPGP encrypted cipherTexts (i mostly think it's because of => https://github.com/bcgit/bc-java/pull/1938) ?

I could see this because if i run the above code in 1.78 encrypted byte size is 40 byte and the same code in 1.80 it gives me 64 bytes !! Yes, i can still decrypt the msg encrypted using 1.78 !! but i would like to have a simple toggle to bring back the old behaviour !

Do you guys have a way to bring back the old behaviour ? If there is a toggle to bring back the old packet size it would be better !

Muthu-Palaniyappan-OL avatar Dec 05 '25 14:12 Muthu-Palaniyappan-OL

TO be precise the issue is from https://github.com/bcgit/bc-java/commit/24db506980df57dbbdae5b75e33e6c889ad0cfde

Image

This is commit is changing the packet length !!

Muthu-Palaniyappan-OL avatar Dec 06 '25 01:12 Muthu-Palaniyappan-OL

Can i get your eyes into this issue @vanitasvitae @ligefeiBouncycastle ☝️ ?

Muthu-Palaniyappan-OL avatar Dec 07 '25 02:12 Muthu-Palaniyappan-OL

Looking into it.

The old packet (generated with 1.79) looks like this.

The new packet (1.81) looks like this.

Some context: With password based encryption, there are two ways to use the key derived from the password to encrypt/decrypt the message: Use the result of applying the S2K function as a key-encryption key and encrypt a random session key with it, which in turn is used to encrypt/decrypt the message payload. This is the standard way of doing message encryption, as it also works with public-key encryption and also works if multiple encryption methods (passwords, public keys) are used to encrypt the message.

Then there is the "direct-s2k" method, which some legacy implementations use when only a single, encryption method (which MUST be a password-based method) is used to encrypt the message. In this case, the result of the s2k function is used directly to encrypt/decrypt the message payload. See this section in the rfc.

The change in packet length is caused by a slight mistake in the code here.

Previously, nSessionInfo was passed in, which would be null for directS2K encrypted messages. For the v6 rework, this call was changed to pass in the prepared sessionKey instead (because v6 packets encode the session key differently than v4 packets). The sessionKey is not null in any case, hence it gets encrypted and the result appended to the SKESK packet, resulting in additional 24 bytes of length.

This needs to be fixed by passing in null instead of sessionKey if directS2K is true. I will prepare a patch.

With the patch applied, the encrypted message looks like this.

As you can see, the lengths are consistent again.

Thanks for reporting this!

vanitasvitae avatar Dec 09 '25 10:12 vanitasvitae