How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?
Asked Answered
G

14

195

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
Gravelly answered 23/7, 2012 at 17:10 Comment(1)
I wouldn't necessarily rely on that code. Things like 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 plain URLConnection to start with. Are you sure you've modified cacerts in lib/security of your JRE installation? Have you tried the trustmanager debugging option?Fairman
U
280

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 www.example.com:443 | \
   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
Underachieve answered 23/7, 2012 at 17:43 Comment(9)
The main idea from this is not portecle but importing certificates into the right keystore.Footie
This worked, but my java was in a different location. My keystore was located at /usr/lib/jvm/java-openjdk/jre/lib/security/cacerts which I found by running ps -ef | grep java which told me my java was running from openjdk located at /usr/lib/jvm/java-openjdk/bin/java. Also, if this if for a webapp remember to restart. Thanks for the help!!Animated
I haven't used portecle, but I found that Keystore Explorer works pretty well for Windows, Linux, (and it should work on OSX as well)Febricity
Very helpful indeed. 2 very important things highlighted here. One is about importing in the right keystore. And another one is to make sure to restart in case of a webserver.Ashlan
Just to complete, use $ sudo keytool -list -keystore cacerts | grep mycert to check if the import was successfull. Add -v parameter to list the certificates with more verbose.Bartle
In 2019, we can even get SSL certificates for free using services like Lets encryptHenceforward
Just a FYI, works just as well on MacOS following the steps for LinuxTijuana
Add -showcerts param to openssl to list all chain certs and choose the highest certificate in the chain hierarchy.Atul
java11+ keytool allows to use -cacerts param instead of -keystore filenameAtul
S
63
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"
Standpipe answered 19/3, 2015 at 1:4 Comment(2)
You will be prompted for the keystore password, the default is "changeit"Kong
At least in java 11 (sapmachine jre) the syntax changed slightly according to the manfile: keytool.exe -importcert -file <path to cer file> -cacerts -alias "<your alias>"Uraninite
G
36

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 https://github.com/ssbarnea/keytool-trust

#!/bin/bash
# version 1.0
# https://github.com/ssbarnea/keytool-trust
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/1.6.0.jdk/Contents/Home/lib/security/cacerts" \
    "/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/lib/security/cacerts"
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

```

Gravelly answered 4/2, 2015 at 14:48 Comment(3)
"sudo keytool" NOPEEndosmosis
/Applications/Xcode.app/Contents/Applications/Application Loader.app no longer exists -- is there a different place Xcode keeps its Java version?Hatchery
@Hatchery See this answer for how to find where your active Java installation is on macOS.Tarsometatarsus
T
26

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
Tarsometatarsus answered 1/7, 2021 at 16:53 Comment(0)
A
19

This worked for me. :)

sudo keytool -importcert -file filename.cer -alias randomaliasname -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit 
Aconcagua answered 23/3, 2017 at 7:14 Comment(3)
Note that you can use the -cacerts option instead of providing the path using -keystore. This is useful because the exact path varies depending on if you have installed a jdk or jre.Tarsometatarsus
@Tarsometatarsus Also note that the -cacerts option is only for Java 9 and aboveCorncob
@MuizzMahdy That's right, see also my detailed answer here.Tarsometatarsus
C
5

If you are using a certificate signed by a Certificate Authority that is not included in the Java cacerts file by default, you need to complete the following configuration for HTTPS connections. To import certificates into cacerts:

  1. Open Windows Explorer and navigate to the cacerts file, which is located in the jre\lib\security subfolder where AX Core Client is installed. The default location is C:\Program Files\ACL Software\AX Core Client\jre\lib\security

  2. Create a backup copy of the file before making any changes.

  3. Depending on the certificates you receive from the Certificate Authority you are using, you may need to import an intermediate certificate and/or root certificate into the cacerts file. Use the following syntax to import certificates:

    keytool -import -alias <alias> -keystore <cacerts_file> -trustcacerts -file <certificate_filename>

  4. If you are importing both certificates the alias specified for each certificate should be unique.

  5. Type the password for the keystore at the “Password” prompt and press Enter. The default Java password for the cacerts file is “changeit”. Type ‘y’ at the “Trust this certificate?” prompt and press Enter.

Chiliad answered 8/5, 2015 at 10:53 Comment(1)
Use this command :-> keytool -import -alias <alias> -keystore <cacerts_file> -trustcacerts -file <certificate_filename>Chiliad
E
2

Fist get the certificate from the provider. Create a file ends with .cer and paste the certificate.

Copy the text file or paste it somewhere you can access it then use the cmd prompt as an admin and cd to the bin of the jdk; the command that will be used is the: keytool

Change the password of the keystore with:

keytool -storepasswd -keystore "path of the key store from c\ and down"

The password is : changeit

Then you will be asked to enter the new password twice. Then type the following:

keytool -importcert -file "C:\Program Files\Java\jdk-13.0.2\lib\security\certificateFile.cer" -alias chooseAname -keystore  "C:\Program Files\Java\jdk-13.0.2\lib\security\cacerts"
Emrick answered 21/7, 2020 at 3:25 Comment(0)
A
1

The simple command 'keytool' also works on Windows and/or with Cygwin.

IF you're using Cygwin here is the modified command that I used from the bottom of "S.Botha's" answer :

  1. make sure you identify the JRE inside the JDK that you will be using
  2. Start your prompt/cygwin as admin
  3. go inside the bin directory of that JDK e.g. cd /cygdrive/c/Program\ Files/Java/jdk1.8.0_121/jre/bin
  4. Execute the keytool command from inside it, where you provide the path to your new Cert at the end, like so:

    ./keytool.exe -import -trustcacerts -keystore ../lib/security/cacerts  -storepass changeit -noprompt -alias myownaliasformysystem -file "D:\Stuff\saved-certs\ca.cert"
    

Notice, because if this is under Cygwin you're giving a path to a non-Cygwin program, so the path is DOS-like and in quotes.

Algarroba answered 4/8, 2017 at 17:36 Comment(0)
M
0

Might want to try

keytool -import -trustcacerts -noprompt -keystore <full path to cacerts> -storepass changeit -alias $REMHOST -file $REMHOST.pem

i honestly have no idea where it puts your certificate if you just write cacerts just give it a full path

Myxoma answered 14/12, 2016 at 14:42 Comment(0)
S
0

install certificate in java linux

/opt/jdk(version)/bin/keytool -import -alias aliasname -file certificate.cer -keystore cacerts -storepass password

Sitin answered 13/3, 2019 at 16:21 Comment(0)
M
0

In Windows these commands work on the command line:

cd C:\Program Files\Java\jre1.8.0_301\lib\security\
keytool -import -trustcacerts -alias cert_ssl -file C:\opt\esb-config\keystores\cert.cer -noprompt -storepass changeit -keystore cacerts

changeit is the default password for the trust store.

Menu answered 15/11, 2021 at 18:57 Comment(0)
E
0

I used below command to import keystore into existing keystore

keytool -importkeystore -srckeystore -destkeystore

Eliath answered 14/7, 2023 at 19:8 Comment(0)
O
0

Keytool to import certs :

keytool -import -trustcacerts -noprompt -keystore cacerts -storepass changeit -alias nexcert -file

Ordure answered 2/8, 2023 at 14:41 Comment(0)
S
0

If you have UI, I suggest to use keystore explorer - https://keystore-explorer.org/

solid software to manage keystores - observe internals, add/remove certificates and so on

Shantung answered 1/3 at 14:11 Comment(1)
degr, a link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it is there, then quote the most relevant part of the page you are linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Aragonite

© 2022 - 2024 — McMap. All rights reserved.