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

Decryption of OpenPGP messages without encrypted session key packets

Open vanitasvitae opened this issue 3 years ago • 4 comments

According to RFC4880, a valid OpenPGP message may not necessarily include an encrypted session key:

   OpenPGP Message :- Encrypted Message [...]

   Encrypted Data :- Symmetrically Encrypted Data Packet |
         Symmetrically Encrypted Integrity Protected Data Packet

   Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data.

(Substitution: OpenPGP Message -> Encrypted Message -> Encrypted Data)

I noticed, that BCs PGPObjectFactory cannot properly parse encrypted data packets if there are no encrypted session key packets (fixed in 5d9a45839a9d129cae0eee6f5dbae7ff40165a91). With that resolved, I noticed that it is not possible to decrypt a message without any encrypted session keys using a session key, since the current implementation requires at least one PKESK/SKESK (Public/Symmetric Key Encrypted Session Key) packet.

As a solution I added the PGPSessionKeyEncryptedData object which allows decryption using a PGPSessionKey. The user can add this manually to a PGPEncryptedDataList by calling pgpEncryptedDataList.addSessionKeyDecryptionMethod(PGPSessionKey sessionKey).

With these patches in place, messages without encrypted session keys can be decrypted :partying_face:!

Perhaps we want to remove the session key decryption on PGPPBEEncryptedData/PublicKeyEncryptedData introduced in https://github.com/bcgit/bc-java/pull/1030 in favor of this for a cleaner API?

vanitasvitae avatar Sep 12 '22 12:09 vanitasvitae

I added isIntegrityProtected() to PGPEncryptedDataList. Before, it was not possible to determine whether a PGPEncryptedDataList was integrity-protected if the list of methods was empty. The PGPEncryptedDataList is probably the better place for this method anyways.

vanitasvitae avatar Sep 13 '22 16:09 vanitasvitae

Okay I've done a bit of work on this now. How's the following look:

   PGPSessionKeyEncryptedData sessionKeyEncData = encryptedData.extractSessionKeyEncryptedData();

    SessionKeyDataDecryptorFactory decryptorFactory = new BcSessionKeyDataDecryptorFactory(sessionKey);

    InputStream decrypted = sessionKeyEncData.getDataStream(decryptorFactory);

Really the data list is already carrying the session key encrypted data, there's no need to pass the session key in twice (actually sometimes there may be very good reasons for not doing so).

dghgit avatar Oct 05 '22 07:10 dghgit

I like your proposal better than my solution :+1:.

vanitasvitae avatar Oct 05 '22 10:10 vanitasvitae

Should be appearing in github shortly. I've deprecated the old methods and marked them for later removal.

dghgit avatar Oct 05 '22 11:10 dghgit