in

GeekyGeeky

Java Key Store (JKS) Complete Guide

All about JKS

Java KeyStore (JKS) is a repository of security certificates plus corresponding private keys. Java-based applications use it for encryption, authentication, and serving over HTTPS.

The Java Development Kit maintains a CA Keystore file named “cacerts” in folder “jre/lib/security/cacerts.” However, this default Keystore will usually have standard root & intermediate certificates and might not work for all the applications. So it’s recommended that we create a different JKS for our application with our list of trusted certificates & the private key.

How do we manage JKS?

Using Java Keytool. Java Keytool is a command-line tool that can generate public key / private key pairs and store them in a Java KeyStore. The Keytool executable is distributed with the Java SDK (or JRE). Therefore, if you have an SDK installed, you will also have the Keytool executable. The Keytool executable is called Keytool.

keytool -import -trustcacerts -file <certificate> -keystore <keystore> -alias <alias>
keytool -list -v -keystore <keystore>
keytool -list -v -keystore <keystore> -alias <alias>
keytool -delete -keystore <keystore> -alias <alias>

How to generate JKS using Certificate & PrivateKey? 

Firstly, Ensure you have the complete chain of trust ( Domain, Intermediates & Root) & private key in PEM encoded format. Remember, The extension doesn’t play any significance here & All that matters is the method of encoding. The extension could be .cer or .crt or .pem or .key or anything for that matter.

PEM encoded certificate files will have a line —–BEGIN CERTIFICATE—–, followed by base64-encoded data, followed by a line —–END CERTIFICATE—–.

Step 1: We cannot directly create a Java Key Store (JKS) using the PEM encoded certificate files. Firstly, we need to create a PKCS12 Keystore first using the below command.

openssl pkcs12 -inkey Private.key -in Certificate.cer -export -out keystore.pkcs12

This command prompts the user for a password. KeyStore fails to work with JSSE without a password.

A PKCS12(Public-Key Cryptography Standards) defines an archive file format for storing server certificates, intermediate certificates ( if any), and private keys into a single encryptable file.

Step 2: Generate JKS using Keytool command with source Keystore as pkcs12 file generated in the previous step.

keytool -importkeystore -srckeystore keystore.pkcs12 -srcstoretype pkcs12 -destkeystore myKeyStore.jks

This command prompts the user for two passwords. One is the source Keystore password, which we entered in the previous step & the other is to secure the destination Keystore (myKeyStore.jks).

It’s recommended to give the same password for both the key stores because JVM has a high chance to fail while loading JKS if these passwords are different.

Why is my JVM failing to send the client certificate?

Case -1: PrivateKey entry is missing
You might have created JKS without having a privateKey entry. Such files might work as Trustore, But not KeyStore. Use the below command to ensure that we have a valid private key entry which is not expired

keytool -list -v -keystore myKeyStore.jks -storepass ****

Case 2: Incomplete chain of trust associated with privateKey entry.
You might have imported all the required entries ( intermediates and root ) separately. But not as a chain tagged to private key entry. You should be able to confirm the same using Keytool.

Let’s consider that we have a client certificate with chain length 3. That means we will have one intermediate & one root.

Failure Scenario:

$ keytool -list -v -keystore myKeyStore.jks -storepass ****|more
Keystore type: JKS
Keystore provider: SUN
 
Your keystore contains 1 entry
 
Alias name: 1
Creation date: Apr 9, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 1

Successful Scenario:

$ keytool -list -v -keystore myKeyStore.jks -storepass ****|more
Keystore type: JKS
Keystore provider: SUN
 
Your keystore contains 2 entries
 
Alias name: 1
Creation date: Apr 9, 2020
Entry type: PrivateKeyEntry
Certificate chain length: 3

As you could see, the certificate chain length is 1 & 3 in failure & successful scenarios, respectively. We might have the complete chain of trust in the JKS but not in association with private key entry. In such cases, we need to import the entire chain of trust with the same alias as that of the private key to tag the chain to private key entry.

What is the difference between a keyStore & a Truststore?

Even though the format is the same, The use & type of entries will be different in these two files.

A Java Keystore stores private key entries, certificates with public keys, or just secret keys that we may use for various cryptographic purposes. It stores each by an alias for ease of lookup.

A trust store is the opposite – while a Keystore typically holds onto certificates that identify us, a Truststore holds onto certificates that identify others.

So in simple words, the one that must contain privateKey entry is KeyStore. The one that can exist without a private key entry is Truststore.

One single file can used as both trustStore & keyStore.

How would JVM find my keyStore & Truststore?

JVM would look for the below arguments to locate & load the JKS files.

-Djavax.net.ssl.keyStore=/path/ks-name
-Djavax.net.ssl.trustStore=/path/ts-name
-Djavax.net.ssl.keyStorePassword=****
-Djavax.net.ssl.trustStorePassword=****

Is there any easy way to list the subjects in a bundle?

We might come across a bundle of PEM encoded certs, making it very difficult to list all the certificates that are part of. So we can use the below script to iterate through all the entries in the bundle & do OpenSSL to show us the subject list.

while read line
 do
  if [ "${line//END}" !="$line" ]; then
    txt="$txt$line\n"
    printf -- "$txt" |openssl x509 -subject -noout
    txt=""
  else
    txt="$txt$line\n"
  fi
done < /path/to/bundle/file

What do you think?

113 Points
Upvote Downvote

Written by admin

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

GIPHY App Key not set. Please check settings