Search code examples
javabouncycastlepublic-key

How to export public key from pkcs12 file programmatically


I am having trouble trying to export a public key contained in a pkcs12 file. What I am trying to achieve is the same result than with this command (but programmatically):

keytool -export -alias mycertalias -keystore mykeystore.jks -rfc -file mypublickey.pem 

I obtain the public key and generate a string with BouncyCastle, but the obtained result doesn't match what I obtain with the command above. Here is my code:

KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(new FileInputStream(certPath),certPassword.toCharArray());
String alias = "mycertalias";
Certificate cert = keyStore.getCertificate(alias);

PublicKey publicKey = cert.getPublicKey();   
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(new PemObject("CERTIFICATE", publicKey.getEncoded()));
pemWriter.flush();
pemWriter.close();

System.out.println(writer.toString());

I have tried not using BouncyCastle and directly encoding the string, but I get the same result than before (so it doesn't match either with the result obtained with the keytool command):

Certificate cert = keyStore.getCertificate(alias);
BASE64Encoder encoder = new BASE64Encoder();
PublicKey publicKey = cert.getPublicKey();
System.out.println(new String(encoder.encode(publicKey.getEncoded())));

Any idea of what am I doing wrong? Thanks for the help in advance.

UPDATE:

As suggested by @dave_thompson_085 what I actually want is to export the whole certificate in PEM format, so the valid code is like this:

//...
Certificate cert = keyStore.getCertificate(alias);
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));
//...

Thanks!


Solution

  • Your keytool example does a JKS not a P12, but adding -storetype pkcs12 would do P12 so I'll assume that's what you meant. More importantly, keytool -exportcert (which officially superseded -export in about 1.5) exports the whole certificate, not just the public key. Specifying -rfc does it in PEM format, and omitting -rfc does it in DER format, but either way it's the whole certificate.

    Also your second code should not produce the same result; it should produce, perhaps modulo line breaks, the same as the body of the PEM format, but without the dashed BEGIN and END lines. The BEGIN and END lines are part of the PEM format, and without them it's not PEM. And without stating the correct type of the contents, which you don't, it's not correct PEM.

    If you really want just the publickey you can do that, but don't expect it to be the same as the certificate because a publickey is not a certificate. Note that there there are very few applications that can use a publickey by itself without the other data in the certificate; the only one that springs to mind is SSH (which supposedly confirms the identity and validity manually), and OpenSSH does not use the ASN1-based "X509" (really SPKI) encoding supported by Java JCE but instead its own base64-MPI-based encoding.