Exporting the Private Key from a JKS keystore

Java - 37 Comments » - 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 | 37 Comments »

37 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. 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. [...] 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. 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. Well, how about only using keytool and openssl? Here’s how you do it: http://www.swview.org/node/191

  20. mahesh says:

    How to import private key into keystore?

    I want to do it using keytool, not using java class.

  21. Dave says:

    I found this post useful as well – and it worked for me…

    “Exporting keystore private key with WSAS”

    http://blog.facilelogin.com/2008/07/exporting-keystore-private-key-with.html

  22. vijai says:

    Key key=keystore.getKey(alias,password);
    if(key instanceof PrivateKey) {

    }

    The key is not an instanceof PrivateKey

    so it is throwing the following error.

    java.lang.NullPointerException at ExportPrivateKey1.export(ExportPrivateKey1.java:81)
    at ExportPrivateKey1.main(ExportPrivateKey1.java:117)
    Exception in thread "main"

    please tell me how to proceed.

    my java version is 1.4

    this is the way i have created keystores

    keytool -genkey -alias a -keyalg RSA -validity 90 -storepass offline -ke
    ystore a.p12

    keytool -genkey -alias b -keyalg RSA -validity 90 -storepass offline -ke
    ystore b.p12

    --------- i exported via keytool its working
    keystore -export -keystore b.p12 -storepass offline -file f1.cer -alias b

    keytool -export -keystore b.p12 -storepass offline -file f1.cer -alias b

    keytool -import -keystore a.p12 -storepass offline -alias b -file f1.cer

  23. Matt McCall says:

    How do I resolve the null point er exception?
    C:\Temp\ExportPKey>11:31:13.54>java -jar ExportPrivateKey.zip pskey JKS OrclSoft
    jobs.bnl.gov privkey.txt
    Exception in thread “main” java.lang.NullPointerException
    at ExportPrivateKey.export(ExportPrivateKey.java:43)
    at ExportPrivateKey.main(ExportPrivateKey.java:61)

    C:\Temp\ExportPKey>11:31:28.43>dir *.zip
    Volume in drive C has no label.
    Volume Serial Number is 2C44-A0AD

    Directory of C:\Temp\ExportPKey

    09/27/2007 02:59 PM 2,292 ExportPrivateKey.zip
    1 File(s) 2,292 bytes
    0 Dir(s) 2,351,157,248 bytes free

    C:\Temp\ExportPKey>11:31:54.87>dir pskey
    Volume in drive C has no label.
    Volume Serial Number is 2C44-A0AD

    Directory of C:\Temp\ExportPKey

    09/22/2008 12:09 PM 15,979 pskey
    1 File(s) 15,979 bytes
    0 Dir(s) 2,351,157,248 bytes free

    C:\Temp\ExportPKey>11:32:00.79>

  24. Matt McCall says:

    I found the problem, incorrect alias name!
    Thanks Anyway

  25. Michael says:

    this only works if alias passwd equal to keystore passwd, corrected code below:

    import org.apache.log4j.Logger;
    import sun.misc.BASE64Encoder;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileWriter;
    import java.security.*;
    import java.security.cert.Certificate;

    public class ExportPrivateKey {
    private static final Logger _logger = Logger.getLogger(”utils.ExportPrivateKey”);

    private File keystoreFile;
    private String keyStoreType;
    private char[] password;
    private String alias;
    private File exportedFile;
    private char[] alias_password;

    public static KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) {
    try {
    Key key=keystore.getKey(alias,password);
    if(key instanceof PrivateKey) {
    Certificate cert=keystore.getCertificate(alias);
    PublicKey publicKey=cert.getPublicKey();
    return new KeyPair(publicKey,(PrivateKey)key);
    }
    } catch (UnrecoverableKeyException e) {
    _logger.fatal(”Cannot access private key”, e);
    } catch (NoSuchAlgorithmException e) {
    _logger.fatal(”Cannot access private key”, e);
    } catch (KeyStoreException e) {
    _logger.fatal(”Cannot access private key”, e);
    }
    return null;
    }

    public void export() throws Exception{
    KeyStore keystore=KeyStore.getInstance(keyStoreType);
    BASE64Encoder encoder=new BASE64Encoder();
    keystore.load(new FileInputStream(keystoreFile),password);
    KeyPair keyPair=getPrivateKey(keystore,alias,alias_password);
    PrivateKey privateKey=keyPair.getPrivate();
    String encoded=encoder.encode(privateKey.getEncoded());
    FileWriter fw=new FileWriter(exportedFile);
    fw.write(”—–BEGIN PRIVATE KEY—–\n”);
    fw.write(encoded);
    fw.write(”\n”);
    fw.write(”—–END PRIVATE KEY—–”);
    fw.close();
    }

    public static void main(String args[]) throws Exception{
    ExportPrivateKey export=new ExportPrivateKey();
    export.keystoreFile=new File(args[0]);
    export.keyStoreType=args[1];
    export.password=args[2].toCharArray();
    export.alias=args[3];
    export.alias_password=args[4].toCharArray();
    export.exportedFile=new File(args[5]);
    export.export();
    }
    }

  26. Michael says:

    note that parameter list is changed, you need to specify alias password after alias name

  27. Daniel says:

    got also some sample code at the following url:

    http://proghowto.com/move-a-private-key-between-two-jks-keystore

    if you are interested on how to move the keys from a keystore to the other one

    Daniel

  28. raffaele says:

    very very usefull

    thank you ;)

  29. titopy says:

    Anand++.
    Worked for me, thanks!

  30. This is very useful, thanks a lot for the info.

  31. Vincent says:

    Sorry, this does NOT work for me.
    I still have a nullpointer exception.
    This the command I use, I know the keystore pwd and alias name are correct, since i opened it with keytool.

    java -jar ExportPrivateKey.zip agent.truststore JKS changeit bla.domain.nl test.pem

    Can anyone provide a solution?

  32. Adam says:

    If you get a null pointer exception and the keystore and private key password are different then change the keystore password to be the same as the private key. This worked for me. The command to change the keystore password is:

    keytool -storepasswd -keystore {keystore_path}

  33. Ryan says:

    I also get NullPointerException error. My keystore and private key password is the same. Any ideas?

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

  34. lefty.crupps says:

    Getting this error:

    Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 4
    at ExportPrivateKey.main(ExportPrivateKey.java:60)

  35. Sash says:

    I have found a bit corrected code on http://www.memofy.com/memofy/show/000863e71fa863e7008545a7bfe138/How_to_export_private_key_from_SUN_keystore
    Supports different password for key and keystore.

    java ExportPrivateKey keystoreFile keyStoreType password keypassword alias

  36. MCSE Guy says:

    Is Gettting MCSE Certified that important?

Leave a Reply