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
Earlier Java versions
With Java 8 (aka 1.8) or older, you must specify the keystore location like so
keytool -importcert -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -file myCert.pem -alias myCert
With Java 5 (aka 1.5) or older, the -importcert
option did not exist. It was called -import
, but otherwise it's identical. So use
keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -file myCert.pem -alias myCert
Additional options
- You will be asked for the truststore password, The default password is changeit.
- If you need to run the import unattended, you can add
-storepass changeit -noprompt
Formats
keytool
can import X.509 v1, v2, and v3 certificates, and PKCS#7 formatted certificate chains consisting of certificates of that type (P7B). The data to be imported must be provided
- either in binary encoding format (DER)
- or in printable encoding format (aka base64 encoded), enclosed in
-----BEGIN
and -----END
lines (PEM)
Note: I'm not sure if certificate chains in PEM format really work.
Bonus script
I'm afraid, it's bash, so no solution for Windows users.
This simple script, created thanks to several useful questions and smart answers here on stackoverflow, checks the Java version and - if necessary - determines the correct keystore location, and it can import multiple certificates in one command. Note that you must pass the file pattern argument in single quotes (see usage).
addcerts.sh
#!/bin/bash
# Add custom root certificates to Java trust store
if [ "$#" -ne 1 ]; then
SCRIPT=`basename "$0"`
echo "Usage: $SCRIPT 'path/to/certs/*'"
exit 1
fi
CERTFILES=$1
JAVA_VERSION=`java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1`
if (( $JAVA_VERSION >= 9 )); then
CACERTS="-cacerts"
else
# Check where cacerts are located
# differs depending or jdk or jre installed
if [ -d "$JAVA_HOME/jre" ]; then
CACERTS="$JAVA_HOME/jre"
else
CACERTS="$JAVA_HOME"
fi
CACERTS="-keystore $CACERTS/lib/security/cacerts"
fi
# Now add certificates
for CERTFILE in $CERTFILES; do
# Remove path, then suffix to derive alias from filename
ALIAS=${CERTFILE##*/}
ALIAS=${ALIAS%.*}
$JAVA_HOME/bin/keytool -importcert -file "$CERTFILE" -alias "$ALIAS" $CACERTS -trustcacerts -storepass changeit -noprompt
if [ $? -ne 0 ]; then
echo "Failed to add $CERTFILE as $ALIAS to $CACERTS"
exit 1
fi
done
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
are completely unnecessary in the first part. The second doesn't do any cert verification. Try with a plainURLConnection
to start with. Are you sure you've modifiedcacerts
inlib/security
of your JRE installation? Have you tried thetrustmanager
debugging option? – Fairman