1. Overview

Managing and securing private keys is a critical aspect of many applications. Java Keystore (JKS) is a popular format for storing cryptographic keys and certificates.

In this tutorial, we’ll explore two methods for listing and exporting private keys from a keystore: one using the command line and another using Java.

2. Using Command Line

First, we use the keytool utility provided by the JDK to list all entries in the keystore, each including private key, certificate, and alias:

keytool -list -keystore mykeystore.jks -storepass mypassword

In the above command, mykeystore.jks is our keystore file name, and mypassword is its password. The output will look something like:

Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 2 entries

Alias name: privatekey1
Creation date: May 29, 2024
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Example, OU=Development, O=Company, L=City, ST=State, C=Country
...

Alias name: privatekey2
Creation date: May 29, 2024
...

Next, we export the private key we want (-srcalias option) from the JKS file to a PKCS12 (.p12) file:

keytool -importkeystore -srckeystore mykeystore.jks -destkeystore mykeystore.p12 -srcstoretype JKS -deststoretype PKCS12 
  -srcalias privatekey1 -srcstorepass mypassword -deststorepass mypassword

Then we use the openssl command to extract the private key from the PKCS12 keystore:

openssl pkcs12 -in mykeystore.p12 -nocerts -nodes -out privatekey.pem -passin pass:mypassword

This extracts the private key in PEM format. The -nocerts option tells openssl not to output the certificates, and -nodes prevent the private key from being encrypted.

Finally, we convert the PEM private key to PKCS8 format:

openssl pkcs8 -in privatekey.pem -topk8 -nocrypt -out privatekey-pkcs8.pem

The -topk8 option converts the key to PKCS8 format, and the -nocrypt option ensures the key is not encrypted.

The final result will look like:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCymad+US28aEBs
hj5nPJyiPotlyafiJSIKwbOu1rHcUYQukDxzRiKgp/j5dzneWhd7BUKDGLUNPL21
...
k7x6oTwzOTJsWsED69ZOC1E=
-----END PRIVATE KEY-----

3. Using Java

We can also use Java to list private keys from a keystore:

try (InputStream is = new FileInputStream("mykeystore.jks")) {
    // Load the keystore
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    char[] passwordCharArr = "mypassword".toCharArray();
    keystore.load(is, passwordCharArr);

    for (String alias : Collections.list(keystore.aliases())) {
        if (keystore.isKeyEntry(alias)) {
            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry(
              alias, new KeyStore.PasswordProtection(passwordCharArr));
            PrivateKey privateKey = pkEntry.getPrivateKey();
            System.out.println("Alias: " + alias);
            System.out.println("-----BEGIN PRIVATE KEY-----");
            System.out.println(Base64.getMimeEncoder(64, "\n".getBytes())
              .encodeToString(privateKey.getEncoded()));
            System.out.println("-----END PRIVATE KEY-----");
        }
    }
}

Let’s break down our code steps:

  • Load the keystore from a file.
  • Iterate through all aliases in the keystore.
  • Check if it is a key entry (including private keys).
  • Retrieve and print the private key in PKCS8 format.

Additionally, let’s use try-with-resources so we don’t have to worry about closing the InputStream manually.

4. Conclusion

Listing private keys from a keystore can be done using both command line tools and Java programs. The command-line approach is straightforward, while Java allows more flexible and programmatic access to keystore contents.

The example code from this article can be found over on GitHub.