Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse Armored ECC public/private keys (generated from gpg cli) in java

I'm trying to convert an armored ECC gpg key to corresponding java class ECPrivateKey/ECPublicKey.

To generate the key pair I'm using: gpg --expert --full-generate-key

Then selecting (9) ECC and ECC (or (10) ECC (sign only))

Then selecting (3) NIST P-256

Resulting in:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mFIEWUdzwhMIKoZIzj0DAQcCAwQkAvZC1PIJ8ke1myyKhNny9vN78TIYo2MuAOY+
F38L9S3+Za9cKV/iIHOqfapbMoqdSmSnqDkevwQSr5MF2UOXtCJzaWduZWNjIChF
Q0Mgc2lnbiBvbmx5KSA8c3NAc3MuY28+iJAEExMIADgWIQRiC+kefVkjnjKovKy5
XANFl5+n1gUCWUdzwgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRC5XANF
l5+n1mzGAQDsgutymxDTTXPKFfpFFVp4fxacx1MSqxP71gNJYjguXwD8CEXD20Vm
aU1WMi2jU7JC6oJn94Y4vWHwTLOU1zmQ19o=
=swfS
-----END PGP PUBLIC KEY BLOCK-----

-----BEGIN PGP PRIVATE KEY BLOCK-----

lHcEWUdzwhMIKoZIzj0DAQcCAwQkAvZC1PIJ8ke1myyKhNny9vN78TIYo2MuAOY+
F38L9S3+Za9cKV/iIHOqfapbMoqdSmSnqDkevwQSr5MF2UOXAAD9FhS2HZoWOyIi
l9nj+WPa9S1o50jM5bNIRALzcyS8SgoP97Qic2lnbmVjYyAoRUNDIHNpZ24gb25s
eSkgPHNzQHNzLmNvPoiQBBMTCAA4FiEEYgvpHn1ZI54yqLysuVwDRZefp9YFAllH
c8ICGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQuVwDRZefp9ZsxgEA7ILr
cpsQ001zyhX6RRVaeH8WnMdTEqsT+9YDSWI4Ll8A/AhFw9tFZmlNVjIto1OyQuqC
Z/eGOL1h8EyzlNc5kNfa
=qHBB
-----END PGP PRIVATE KEY BLOCK-----

How do I get from this armored text format to a valid java.security.interfaces.ECPrivateKey and java.security.interfaces.ECPublicKey java classes?

My final goal is to sign in the following way:

String createSignatureFromJson(String jsonPayload, byte[] privateKey) {
        Payload payload = new Payload(jsonPayload)
        def key = privateKeyParse(privateKey)

        JWSSigner signer = new ECDSASigner((ECPrivateKey)key)
        JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256).build()

        JWSObject jwsObject = new JWSObject(header, payload)
        jwsObject.sign(signer)
        jwsObject.signature
    }
like image 902
Tomer Mayost Avatar asked Jun 19 '17 15:06

Tomer Mayost


People also ask

How do I export my public GPG key?

To export your public PGP keySelect the GnuPG keys keyring from the left side panel. Select the Personal PGP key that has to be exported, from the list. Select File ▸ Export…. To store the keys in the ASCII format, select Armored PGP keys from the menu above the Export button.

Where does GnuPG store private keys?

The private GPG keys are encrypted and stored in the secret keyring, and public keys are maintained with certificates attesting to their trustworthiness in the public keyring. You can use the public key for the data encryption, and that encrypted data will be decrypted using the Private key.


2 Answers

If you just pass in the 'private key block', this will extract the ECPrivateKey:

private static ECPrivateKey privateKeyParse(byte[] privateKey) throws Exception
{
    InputStream pgpIn = PGPUtil.getDecoderStream(new ByteArrayInputStream(privateKey));

    PGPObjectFactory pgpFact = new PGPObjectFactory(pgpIn, new JcaKeyFingerprintCalculator());
    PGPSecretKeyRing pgpSecRing = (PGPSecretKeyRing)pgpFact.nextObject();
    PGPSecretKey pgpSec = pgpSecRing.getSecretKey();
    PGPPrivateKey pgpPriv = pgpSec.extractPrivateKey(null);

    return (ECPrivateKey)new JcaPGPKeyConverter().getPrivateKey(pgpPriv);
}

To answer a comment question as to how to how to get 'privateKey', if the entire:

-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----

is in a file, then just read the whole file into a byte[]:

InputStream fIn = new BufferedInputStream(new FileInputStream(...));
byte[] privateKey = org.bouncycastle.util.io.Streams.readAll(fIn);
like image 108
Peter Dettman Avatar answered Oct 02 '22 10:10

Peter Dettman


public static ECPrivateKey privateKeyParse(byte[] privateKey) throws Exception {

        InputStream pgpIn = PGPUtil.getDecoderStream(new ByteArrayInputStream(privateKey));

        PGPObjectFactory pgpFact = new PGPObjectFactory(pgpIn, new JcaKeyFingerprintCalculator());
        PGPSecretKeyRing pgpSecRing = (PGPSecretKeyRing) pgpFact.nextObject();
        PGPSecretKey pgpSec = pgpSecRing.getSecretKey();

        PGPPrivateKey pgpPriv = pgpSec.extractPrivateKey(null);

        JcaPGPKeyConverter converter = new JcaPGPKeyConverter();
        // this is the part i was missing from Peter Dettman's answer. pass BC provider to the converter
        converter.setProvider(new BouncyCastleProvider());
        PrivateKey key = converter.getPrivateKey(pgpPriv);
        return (ECPrivateKey) key;
    }
like image 26
Tomer Mayost Avatar answered Oct 02 '22 09:10

Tomer Mayost