I have a server with a self-signed certificate, but also requires client side cert authentication. I am having a rough time trying to get the raw CA server cert so I can import it into a keystore. Anyone have some suggestions on how to easily do that?
5 Answers
Was looking at how to trust a certificate while using jenkins cli, and found https://issues.jenkins-ci.org/browse/JENKINS-12629 which has some recipe for that.
This will give you the certificate:
openssl s_client -connect ${HOST}:${PORT} </dev/null
if you are interested only in the certificate part, cut it out by piping it to:
| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
and redirect to a file:
> ${HOST}.cert
Then import it using keytool:
keytool -import -noprompt -trustcacerts -alias ${HOST} -file ${HOST}.cert \
-keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS}
In one go:
HOST=myhost.example.com
PORT=443
KEYSTOREFILE=dest_keystore
KEYSTOREPASS=changeme
# get the SSL certificate
openssl s_client -connect ${HOST}:${PORT} </dev/null \
| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${HOST}.cert
# create a keystore and import certificate
keytool -import -noprompt -trustcacerts \
-alias ${HOST} -file ${HOST}.cert \
-keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS}
# verify we've got it.
keytool -list -v -keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS} -alias ${HOST}
3 Comments
-noprompt and -storepass you can pipe with no temp file: openssl s_client -connect host:port | keytool -import -noprompt -alias nm -keystore file -storepass pwI use openssl, but if you prefer not to, or are on a system (particularly Windows) that doesn't have it, since java 7 in 2011 keytool can do the whole job:
keytool -printcert -sslserver host[:port] -rfc >tempfile
keytool -import [-noprompt] -alias nm -keystore file [-storepass pw] [-storetype ty] <tempfile
# or with noprompt and storepass (so nothing on stdin besides the cert) piping works:
keytool -printcert -sslserver host[:port] -rfc | keytool -import -noprompt -alias nm -keystore file -storepass pw [-storetype ty]
Conversely, for java 9 up always, and for earlier versions in many cases, Java can use a PKCS12 file for a keystore instead of the traditional JKS file, and OpenSSL can create a PKCS12 without any assistance from keytool:
openssl s_client -connect host:port </dev/null | openssl pkcs12 -export -nokeys [-caname nm] [-passout option] -out p12file
# <NUL on Windows
# default is to prompt for password, but -passout supports several options
# including actual value, envvar, or file; see the openssl(1ssl) man page
BUT (as I apparently hadn't yet found in 2018) this won't work as a truststore with 'standard' (Oracle/OpenJDK) Java crypto because that requires trusted cert(s) in a PKCS12 to have a special attribute OpenSSL doesn't know about. This does work if you install and use the BouncyCastle provider and specify the storetype which can affect (maybe break) other things, AND you specify 'friendly' name(s) with -caname. (corrected: -caname not -name or nm)
3 Comments
keytool :)There were a few ways I found to do this:
- Firefox: Add Exception -> Get Certificat -> View -> Details -> Export...
- KeyMan (http://www.alphaworks.ibm.com/tech/keyman) You can get SSL cert directly from the File -> Import menu
- InstallCert (Code by Andreas Sterbenz)
java InstallCert [host]:[port]
keytool -exportcert -keystore jssecacerts -storepass changeit -file output.cert
keytool -importcert -keystore [DESTINATION_KEYSTORE] -file output.cert
2 Comments
Just expose dnozay's answer to a function so that we can import multiple certificates at the same time.
Save it to a .sh file then run it.
#!/usr/bin/env sh
KEYSTORE_FILE=/path/to/keystore.jks
KEYSTORE_PASS=changeit
import_cert() {
local HOST=$1
local PORT=$2
if [[ -z $PORT ]]; then
PORT=443
fi
# get the SSL certificate
openssl s_client -connect ${HOST}:${PORT} </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${HOST}.cert
# delete the old alias and then import the new one
keytool -delete -keystore ${KEYSTORE_FILE} -storepass ${KEYSTORE_PASS} -alias ${HOST} &> /dev/null
# create a keystore (or update) and import certificate
keytool -import -noprompt -trustcacerts \
-alias ${HOST} -file ${HOST}.cert \
-keystore ${KEYSTORE_FILE} -storepass ${KEYSTORE_PASS}
# remove temp file
rm ${HOST}.cert
}
# Change your sites here
import_cert stackoverflow.com 443
import_cert www.google.com # default port 443
import_cert 172.217.194.104 443 # google