Exporting the Private Key from a JKS keystore

Java - - Posted on January, 19 at 3:22 pm

A common problem faced when moving certificates and keys from tomcat to Apache web server is that keytool does not allow you to export the private key in the format that apache’s modssl module requires. Mark Foster’s post and Andrew Morrow’s post contains valuable information on how to export a key from a JKS keystore.

Here is a summary of the steps needed to export a private key
Download ExportPrivateKey.zip
Invoke

java -jar ExportPrivateKey.zip {keystore_path} JKS {keystore_password} {alias} {target_file}

This would export the key to PKCS #8 PEM format. Now run openssl to convert it to the format apache modssl expects the file in

openssl pkcs8 -inform PEM -nocrypt -in exported-pkcs8.key -out exported.key

The java code for exporting the private key in PKCS #8 format

  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileWriter;
  4. import java.security.Key;
  5. import java.security.KeyPair;
  6. import java.security.KeyStore;
  7. import java.security.KeyStoreException;
  8. import java.security.NoSuchAlgorithmException;
  9. import java.security.PrivateKey;
  10. import java.security.PublicKey;
  11. import java.security.UnrecoverableKeyException;
  12. import java.security.cert.Certificate;
  13.  
  14. import sun.misc.BASE64Encoder;
  15.  
  16. public class ExportPrivateKey {
  17.         private File keystoreFile;
  18.         private String keyStoreType;
  19.         private char[] password;
  20.         private String alias;
  21.         private File exportedFile;
  22.  
  23.         public static KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) {
  24.                 try {
  25.                         Key key=keystore.getKey(alias,password);
  26.                         if(key instanceof PrivateKey) {
  27.                                 Certificate cert=keystore.getCertificate(alias);
  28.                                 PublicKey publicKey=cert.getPublicKey();
  29.                                 return new KeyPair(publicKey,(PrivateKey)key);
  30.                         }
  31.                 } catch (UnrecoverableKeyException e) {
  32.         } catch (NoSuchAlgorithmException e) {
  33.         } catch (KeyStoreException e) {
  34.         }
  35.         return null;
  36.         }
  37.  
  38.         public void export() throws Exception{
  39.                 KeyStore keystore=KeyStore.getInstance(keyStoreType);
  40.                 BASE64Encoder encoder=new BASE64Encoder();
  41.                 keystore.load(new FileInputStream(keystoreFile),password);
  42.                 KeyPair keyPair=getPrivateKey(keystore,alias,password);
  43.                 PrivateKey privateKey=keyPair.getPrivate();
  44.                 String encoded=encoder.encode(privateKey.getEncoded());
  45.                 FileWriter fw=new FileWriter(exportedFile);
  46.                 fw.write(“—–BEGIN PRIVATE KEY—–\n);
  47.                 fw.write(encoded);
  48.                 fw.write(\n);
  49.                 fw.write(“—–END PRIVATE KEY—–”);
  50.                 fw.close();
  51.         }
  52.  
  53.  
  54.         public static void main(String args[]) throws Exception{
  55.                 ExportPrivateKey export=new ExportPrivateKey();
  56.                 export.keystoreFile=new File(args[0]);
  57.                 export.keyStoreType=args[1];
  58.                 export.password=args[2].toCharArray();
  59.                 export.alias=args[3];
  60.                 export.exportedFile=new File(args[4]);
  61.                 export.export();
  62.         }
  63. }

Posted in Java |

19 Responses to “Exporting the Private Key from a JKS keystore”

  1. Derek Helbert Says:

    This was very usefull. I also would like to know how to import public and private keys as well.

  2. anandsekar Says:

    This should work ..

    Key key={load key from file}…
    Certificate cert={load cert from file} …
    KeyStore keyStore = KeyStore.getInstance(”JKS”);
    keyStore.load(null, “password”.toCharArray());
    keyStore.setKeyEntry(”alias”, key, “password”.toCharArray(), cert);

  3. cirkyl Says:

    Great website! Bookmarked! I am impressed at your work!

  4. Avik Sengupta Says:

    Thanks!!! Saved my life!

  5. Eric Lambrecht Says:

    Thanks for publishing this - it was very useful!

  6. Kristina Says:

    Hi. I know this *should* work, and it has worked before, but suddenly I’m getting this every time:

    Exception in thread “main” java.lang.NullPointerException
    at ExportPrivateKey.export(ExportPrivateKey.java:43)
    at ExportPrivateKey.main(ExportPrivateKey.java:61)

    I’ve found other similar export implementations, and they all fail on any line that calls “getPrivate().” Any ideas? This is killing me, and I seem to be the only person in the world to suddenly have this problem. haha!

    Great work, though, and thanks. :-)

  7. gaoshikao Says:

    KeyStore.PrivateKeyEntry
    KeyStore.SecretKeyEntry
    KeyStore.TrustedCertificateEntry

    is your code only useful for the first method?

  8. Exporting private key from keystore for use with Postfix/Apache - Zimbra - Forums Says:

    […] or removed and it consequently becomes difficult to find. The following instructions are from this page, which originally got them from here. Here is a summary of the steps needed to export a […]

  9. tcwinn Says:

    This is excellent! I really needed this tonight. Thank you for posting.

  10. Shelly Says:

    How do I export a public key from a keystore? Can I use the same program by just changing the APIS to getpublic key. Also how I convert a generated public key to OPENSSL complaint format. Appreciate any help on this!

  11. Ludovic Says:

    A question:

    Why do you:

    {code}
    PrivateKey privateKey=keyPair.getPrivate();
    String encoded=encoder.encode(privateKey.getEncoded());
    {code}

    And then suggest to:
    {{openssl pkcs8 -inform PEM -nocrypt -in exported-pkcs8.key -out exported.key}}

    Isn’t there a simple way of doing that, by directly recover the uncrypted key from the privateKey object ?

  12. anandsekar Says:

    This is because apache expects the key to be in PKCS8 format, which is different from what JKS stores, so we need openssl to convert to PKCS8

  13. jp Says:

    Has anybody tried and got it to work in real world? I’m curious. I didn’t seem to have any success myself.

    Thanks,
    jp

  14. Anon Says:

    I’ve failed to get the code to work. Keep having “Password tampered” error. And then I found that the code assume that the storepass and keypass are the same.

  15. Daryl Says:

    It worked for me. Thanks!

  16. Prince Nishchal Says:

    Dear Anand,

    Your program made our day. Thanks a lot.

    Regards,
    Prince Nishchal.N.E

  17. Pat Rouso Says:

    Does someone know how to convert the PKCS#8 PEM format to SSL PEM format directly in Java (so without the openssl tool)?

  18. Egor Says:

    Thanks for your help!
    It really helps me!

    The error of tempered keystore sais that you lanch program with wrong keystore name.

    If we get NullPointer error, it means that Password for keystore is correct, but alias (with name you entered) is not in this keystore!
    You need to find out a valid alias-name.

    И для русских:
    прога действительно работает!!! :)
    Если вылезает ошибка tempered keystore, это значит, что вы указали неправильный пароль для keystore.
    Если вылезает ошибка NullPointer error, значит пароль правильный, но вы указали неправильное имя alias

  19. Kamal Wickramanayake Says:

    Well, how about only using keytool and openssl? Here’s how you do it: http://www.swview.org/node/191

Leave a Reply