Search code examples
javabouncycastlegnupg

BouncyCastle - GPG. Extract Public Key from Secret Key


I'm using this java code to extract the public key from secret key:

PGPSecretKeyRingCollection ring = new PGPSecretKeyRingCollection(decoderStream,
            new JcaKeyFingerprintCalculator());
Iterator<PGPSecretKeyRing> it = ring.getKeyRings();
while (it.hasNext()) {
    PGPSecretKeyRing key = it.next();
    Iterator<PGPPublicKey> itpublic = key.getPublicKeys();
    while (itpublic.hasNext()) {
        PGPPublicKey pubKey = itpublic.next();
        // use this pubKey
    }
}

If I try to export that key in an ArmoredOutputStream, I get something like:

    -----BEGIN PGP PUBLIC KEY BLOCK-----
    Version: BCPG v1.66
    
    hQEMA6GfAr1vmvVrAQf/XF/6DqSxZu0dXXVnhfxoot+YTLBrwnec/af72R8G1aJI
    [...]
    =eLkg
    -----END PGP PUBLIC KEY BLOCK-----

If I use this key to encrypt something from java code, everything works fine.

If I use this key to encrypt files from command line (or other clients like Kleopatra):

$ gpg --import pubKey.gpg
$ gpg --encrypt ...

I get the "Unusable public key" error.

Am I doing something wrong with the public key export from java code?


Solution

  • You have to use all the PublicKeyRing, not only the master public key:

    List<PGPPublicKey> list = new ArrayList<>();
    Iterator<PGPSecretKeyRing> it = ring.getKeyRings();
    while (it.hasNext()) {
        PGPSecretKeyRing secretRing = it.next();
        Iterator<PGPPublicKey> itpublic = secretRing.getPublicKeys();
        while (itpublic.hasNext()) {
            PGPPublicKey pub = itpublic.next();
            list.add(pub);
        }
        Iterator<PGPPublicKey> itextrapublic = secretRing.getExtraPublicKeys();
        while (itextrapublic.hasNext()) {
            PGPPublicKey pub = itextrapublic.next();
            list.add(pub);
        }
    }
    PGPPublicKeyRing publicRing = new PGPPublicKeyRing(list);
    publicRing.encode(armoredOutputStream)