How do I store and read PGP public keys as strings using Bouncycastle Java?
bouncycastle, java, pgp, public-key
Solution
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()`.
Problem
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?