I have been trying to create, encode, store, retrieve, and decode a Bouncy Castle PGP public key. I get what appears to be the wrong output and an EOFException when I try to read the key back in. The key will be stored in a database as a string.
The original RSA encryption public key is extracted from the key ring as follows:
@SuppressWarnings("unchecked")
public PGPPublicKey getPublicKey() {
    PGPPublicKey pk = null;
    Iterator<PGPPublicKey> it = publicKeyRing.getPublicKeys();
    while (pk == null && it.hasNext()) {
        PGPPublicKey key = it.next();
        if (key.isEncryptionKey()) {
            pk = key;
        }
    }
    return pk;
}
It is encoded, ASCII armored, and stored as a string as follows:
    PGPPublicKey contactPK = realContact.getPublicKey();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ArmoredOutputStream armored = new ArmoredOutputStream(out);
    contactPK.encode(armored);
    armored.close();
    publicKey = new String(out.toByteArray(), Charset.forName("US-ASCII"));
This gets me a PGP message block where I would expect a PGP public key block:
-----BEGIN PGP MESSAGE-----\nVersion: BCPG v1.50\n\nuQINBFO8StkCEACQ4vrDnBTDjEvQkGwrAHuJSBZL8tNLxhZ9B74afhObhLVzW6ZB\nT3pk/5XcSPOTvcWd9k1yOKJUabCuF5ixFmMz+niFqUVQTtnl7aqOZ+GrDEzmoYmG\nNQROP0EiA1TWtm2+Ja0FqiJauXytt1sIF/Pr5L47FCjtmZKVoXTP8RVFfGLPB0kT\ndjOz53PaEE3GSValh85w24XIH2/gczURUnjphCX1bRwTFr14SfA9X/rFWqv9SqWQ\nV8OiIWrSiwNd5RLJ9q0B+viDzoxrjmnMJZikxhKiuNVKJCu2ccBdMrbW42iBM2w3\n
... (for brevity)
\n-----END PGP MESSAGE-----
When I try to read the string back in to recreate the public key, I get an EOFException:
// Import the public key.
ByteArrayInputStream in =
        new ByteArrayInputStream(stored.publicKey.getBytes(
                                                    Charset.forName("US-ASCII")));
// Needed to read ASCII armored keys
InputStream decoded = PGPUtil.getDecoderStream(in);
BCPGInputStream bcpgIn = new BCPGInputStream(decoded);
RSAPublicBCPGKey bcpgKey = new RSAPublicBCPGKey(bcpgIn);
PublicKeyPacket pkPacket = new PublicKeyPacket(PublicKeyAlgorithmTags.RSA_ENCRYPT,
                                                new Date(), bcpgKey);
publicKey = new PGPPublicKey(pkPacket, new BcKeyFingerprintCalculator());
The exception occurs when I create the RSAPublicBCPGKey.
I am doing something very wrong, but I can't figure out what it is. Can anyone help?
Say you already have your pgp public key (ascii armored) in a String str:
    InputStream in=new ByteArrayInputStream(str.getBytes());
    in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
    JcaPGPPublicKeyRingCollection pgpPub = new JcaPGPPublicKeyRingCollection(in);
    in.close();
    PGPPublicKey key = null;
    Iterator<PGPPublicKeyRing> rIt = pgpPub.getKeyRings();
    while (key == null && rIt.hasNext())
    {
        PGPPublicKeyRing kRing = rIt.next();
        Iterator<PGPPublicKey> kIt = kRing.getPublicKeys();
        while (key == null && kIt.hasNext())
        {
            PGPPublicKey k = kIt.next();
            if (k.isEncryptionKey())
            {
                key = k;
            }
        }
    }
    return key;
Now, your variable key will have your PGPPublicKey.
I ran into this issue, and it turned out that the Public Key Ring was actually the public key itself. When I was running the iterator I was actually getting subkeys (which turns into that message block instead of the public key block). If I'm not explaining that well, check out this explanation.
Assuming realContact is a public key ring that only contains subkeys, you don't actually need to run it through getPublicKey().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With