Building a custom PKCS12 Truststore for Java

When connecting to an HTTPS service, custom truststore is required to be added to Java platforms to allow them. An alternative approach is to add all the certificates chain to default cacerts JDK file, but this blog post describes the creation of a new truststore to be used by the application with the following environment variables:

  • javax.net.ssl.trustStore: location of the keystore file
  • javax.net.ssl.trustStoreType: type of the keystore (PKCS12 in this sample)
  • javax.net.ssl.trustStorePassword: password used to protect the keystore

Using only openssl commands is not enough, since Java is not accepting standard PKCS12 truststores produced by this tool. Java only supports trusted certificates in PKCS12 if they are marked with a special attribute (OID 2.16.840.1.113894.746875.1.1) that is not available to be added with openssl. For this reason, Java keytool is also required to create this truststore.

Once both tools (openssl & keytool) are available in your working environment, get all the certificates chain from the HTTPS service you want to connect to.

openssl s_client -showcerts -verify 5 -connect ${HOSTNAME}:443 < /dev/null |
   awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}'
for cert in *.pem; do
        newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
        echo "${newname}"; mv "${cert}" "${newname}"
done

This openssl command will create a collection of PEM files containing all the public certificate chain required to connect to HOSTNAME.

The following lines are building the custom truststore for Java using keytool.

# Since Java doesn't accept default PKCS12 truststores 
# produced with OpenSSL, using keytool is required
for cert in *.pem; do
    keytool -import -alias ${cert} -noprompt -file ${cert} -keystore truststore.pkcs12 -storetype PKCS12 -storepass pass
done

From this point, truststore file can be used by your Java application without issues passing the environment variables

javax.net.ssl.trustStore=truststore.pkcs12
javax.net.ssl.trustStoreType=PKCS12
javax.net.ssl.trustStorePassword=pass

Published by angelborroy

Understanding software.

Leave a comment