bcgit / bc-java

Bouncy Castle Java Distribution (Mirror)
https://www.bouncycastle.org/java.html
MIT License
2.29k stars 1.13k forks source link

Support for GnuPG 2.2 + Private Keys Files #1320

Open Patrick-Harms opened 1 year ago

Patrick-Harms commented 1 year ago

Hi

Apologies in advance for creating a duplicate of the GNUPG 2.2.X file format support (https://github.com/bcgit/bc-java/issues/794). But I need a definitive answer, sooner than later, if possible. So I thought raising it as a new issue, would hopefully gather more attention. 🙏

I have some two modules, that were developed back in 2014/2015, that does OpenPGP signing/encryption and decryption/verification using Bouncy Castle. It all works fine. I now have a client, that wants these modules to work with the latest GnuPG. However, I see that GnuPG changed the format of the files with their 2.2.1 release on 19th September 2017 see this archived news release link (https://lists.gnu.org/archive/html/info-gnu/2017-09/msg00010.html). With more detail in this link (https://gnupg.org/faq/whats-new-in-2.1.html).

With release 2.2 , private/secret keys are no longer in the secring.gpg file, they are now stored as separate files in a sub-directory named private-keys-v1.d. Public keys are no longer in the pubring.gpg file, they are now stored in a Keybox file named pubring.kbx.

Looking at the latest Bouncy Castle PGP code/javadoc, there doesn't appear to be any support at all for the private/secret keys stored in the private-keys-v1.d directory. There appears to be some support for the public key Keybox file, but I'm unsure whether that is integrated enough to do encryption and signature verification operations.

Does anyone know, if I'm wrong with my above statement. And that Bouncy Castle can work with the new 2.2 private/secret keys private-keys-v1.d directory . And if so, is there any example code.

Or do I need to migrate off Bouncy Castle and either write my own library from scratch (which will take a lot of effort) or use a paid library like IPWorks OpenPGP from /nsoftware (https://www.nsoftware.com/ipworks/pgp/).

Regards Pat

Patrick-Harms commented 8 months ago

FYI. I ended up writing code that worked off an exported secret key file. It wasn't ideal, but it works. The code was non-trivial in what it had to do to parse the exported secret key file.

bodhi-one commented 7 months ago

@Patrick-Harms - I also have a need for this. I have emailed BC team a couple of times. To them it might be easy to figure it out so I didn't get a usable response. BC, which has been a core of my teams, and many other teams toolbox for a long time, has not yet recognized the need to do this for the community.

bodhi-one commented 7 months ago

@Patrick-Harms - is it that the secret keys just cannot be placed in the kbx file? I thought they could. We were having an issue of reading them out of there as the BC API doesn't support it.

Patrick-Harms commented 7 months ago

@bodhi-one , yes it is a surprise, that there is no high level BC API code to read the secret keys from the GNUPG 2.2.X file format, which stores them as separate files in a sub-directory named private-keys-v1.d .

The public keys are in the .kbx file. The public key access was sort of straight forward from the BC API. I used the org.bouncycastle.gpg.keybox.bc.BcKeyBox object to parse the read in keybox file (I used aBufferedInputStream object wrapped around a FileInputStream object). Parsing the various BLOB objects that it was formatted as, see the org.bouncycastle.gpg.keybox package. First the FIRST_BLOB object, and then the OPEN_PGP_BLOB objects. From the OPEN_PGP_BLOB object, I was able to create the org.bouncycastle.openpgp.PGPPublicKeyRing object.

The secret key, as my application normally only has one key, I exported it using the gpg --export-secret-keys command with the --armor option, to create an ASCII Base64 encoded file. Then in my application, I used the Bouncy Castle org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory object to parse the Base64 decoded bytes from the read in exported key file, into an org.bouncycastle.openpgp.PGPSecretKeyRing object. With that retrieved, the code was then easy.

cstamas commented 7 months ago

On a related note, reading keys from private-keys-v1.d is possible with SExprParser, but it does not work for ed25519 keys (that are becoming de facto standard and default these days). For example jgit does that https://github.com/eclipse-mirrors/org.eclipse.jgit/blob/master/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgKeyLocator.java but fails badly if private key is ed25519.

Recorded related issue https://github.com/bcgit/bc-java/issues/1590

eirnym commented 3 months ago

any news on this topIc?

bodhi-one commented 3 months ago

any news on this topIc?

I have emailed bc team twice asking for this. Apparently they don't think it's important and/or necessary. Even in the days of hsms and kek/dek, we still need pgp keys into the long term future to exchange data with customers.

bodhi-one commented 3 months ago

any news on this topIc?

Our work around is to keep a rhel 7 container around and keep using pre-kbx gpg. It's a kludge but it works.

eirnym commented 3 months ago

I understand backward compatibility and this issue is not about to remove it. This issue is about to add a step forward.