How to Properly Import a Selfsigned Certificate into Java Keystore That Is Available to All Java Applications by Default?

I do want to import a self signed certificate into Java so any Java application that will try to establish a SSL connection will trust this certificate.

So far, I managed to import it in

keytool -import -trustcacerts -noprompt -storepass changeit -alias $REMHOST -file $REMHOST.pem
keytool -import -trustcacerts -noprompt -keystore cacerts -storepass changeit -alias $REMHOST -file $REMHOST.pem

Still, when I try to run HTTPSClient.class I still get:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
1

11 Answers

On Windows the easiest way is to use the program portecle.

  1. Download and install portecle.
  2. First make 100% sure you know which JRE or JDK is being used to run your program. On a 64 bit Windows 7 there could be quite a few JREs. Process Explorer can help you with this or you can use: System.out.println(System.getProperty("java.home"));
  3. Copy the file JAVA_HOME\lib\security\cacerts to another folder.
  4. In Portecle click File > Open Keystore File
  5. Select the cacerts file
  6. Enter this password: changeit
  7. Click Tools > Import Trusted Certificate
  8. Browse for the file mycertificate.pem
  9. Click Import
  10. Click OK for the warning about the trust path.
  11. Click OK when it displays the details about the certificate.
  12. Click Yes to accept the certificate as trusted.
  13. When it asks for an alias click OK and click OK again when it says it has imported the certificate.
  14. Click save. Don’t forget this or the change is discarded.
  15. Copy the file cacerts back where you found it.

On Linux:

You can download the SSL certificate from a web server that is already using it like this:

$ echo -n | openssl s_client -connect  | \
   sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/examplecert.crt

Optionally verify the certificate information:

$ openssl x509 -in /tmp/examplecert.crt -text

Import the certificate into the Java cacerts keystore:

$ keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts \
   -storepass changeit -noprompt -alias mycert -file /tmp/examplecert.crt
7
    D:\Java\jdk1.5.0_10\bin\keytool -import -file "D:\Certificates\SDS services\Dev\dev-sdsservices-was8.infavig.com.cer" -keystore "D:\Java\jdk1.5.0_10\jre\lib\security\cacerts" -alias "sds certificate"
2

I ended up writing a small script that adds the certificates to the keystores, so it is much easier to use.

You can get the latest version from

#!/bin/bash
# version 1.0
# 
REMHOST=$1
REMPORT=${2:-443}

KEYSTORE_PASS=changeit
KEYTOOL="sudo keytool"

# /etc/java-6-sun/security/cacerts

for CACERTS in  /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts \
    /usr/lib/jvm/java-7-oracle/jre/lib/security/cacerts \
    "/System/Library/Java/JavaVirtualMachines/" \
    "/Applications/ "
do

if [ -e "$CACERTS" ]
then
    echo --- Adding certs to $CACERTS

# FYI: the default keystore is located in ~/.keystore

if [ -z "$REMHOST" ]
    then
    echo "ERROR: Please specify the server name to import the certificatin from, eventually followed by the port number, if other than 443."
    exit 1
    fi

set -e

rm -f $REMHOST:$REMPORT.pem

if openssl s_client -connect $REMHOST:$REMPORT 1>/tmp/keytool_stdout 2>/tmp/output </dev/null
        then
        :
        else
        cat /tmp/keytool_stdout
        cat /tmp/output
        exit 1
        fi

if sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' </tmp/keytool_stdout > /tmp/$REMHOST:$REMPORT.pem
        then
        :
        else
        echo "ERROR: Unable to extract the certificate from $REMHOST:$REMPORT ($?)"
        cat /tmp/output
        fi

if $KEYTOOL -list -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT >/dev/null
    then
    echo "Key of $REMHOST already found, skipping it."
    else
    $KEYTOOL -import -trustcacerts -noprompt -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
    fi

if $KEYTOOL -list -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -keystore "$CACERTS" >/dev/null
    then
    echo "Key of $REMHOST already found in cacerts, skipping it."
    else
    $KEYTOOL -import -trustcacerts -noprompt -keystore "$CACERTS" -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
    fi

fi

done
2

This worked for me. :)

sudo keytool -importcert -file filename.cer -alias randomaliasname -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit 
3

You can use keytool with your Java installation which should be in $JAVA_HOME/bin. The Java keystore is located in $JAVA_HOME/lib/security/cacerts or $JAVA_HOME/jre/lib/security/cacerts which depends on if you have the JDK or JRE installed.

If using Java 9 or later, you don't need to know the exact location. You can use the -cacerts option as a shortcut.

Java 9+

So with Java 9 (aka Java 1.9) or later, simply use

keytool -importcert -trustcacerts -cacerts -file myCert.pem -alias myCert
Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.