4

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!

3
  • pemWriter.writeObject(new PemObject("CERTIFICATE", publicKey.getEncoded())); this line seems iffy to me, you should convert the PublicKey to a Bouncycastle format: SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()); although I think even that step is unnecessary, just write pemWriter.writeObject(publicKey.getEncoded()); Commented Feb 19, 2015 at 20:58
  • The current version of BC's PemWriter only accepts a PemObjectGenerator as argument, it doesn't accept a byte array anymore: public void writeObject(PemObjectGenerator objGen) Commented Feb 19, 2015 at 22:39
  • oh. Nice to know, thanks. I guess I was looking at an older source. Commented Feb 20, 2015 at 6:39

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes sorry about that, my use case is a bit more complicated so for the shake of simplicity in the question I mixed up the keytool command, but it's as you said. You're more than right... In fact what I was looking for was simply this: ... Certificate cert = keyStore.getCertificate(alias); StringWriter writer = new StringWriter(); PemWriter pemWriter = new PemWriter(writer); pemWriter.writeObject(new PemObject("CERTIFICATE", cert.getEncoded())); I am afraid I misunderstood the content of a .pem file! Thank you very much for your help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.