Been dealing with self signed certificate quite sometimes and found myself always googled around for the how-tos, guess it's time to write it down here (for checking back later on which I guess I will... ;)
And here's the famous security exception:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target;
nested exception is 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
Goal is to install a self signed certificate in Java keystore so that Java app can open https connection to the server without raising any security error or trying to skip the security checking at all.
How to:
Step 1. Extracting the certificate
Using openssl:
1. Grab the target certificate from the server
openssl s_client -showcerts -verify 5 -connect {HOST:PORT} | tee thecert.txt
Type QUIT and press enter/return, certificate will be captured in thecert.txt
2. Generate cert file
openssl x509 -inform PEM -in thecert.txt -out thecert.crt
3. Verify cert
openssl x509 -in thecert.crt -text -noout
In case you are dealing with a development environment, you might want to install the root and intermediate cert in your keystore so that you don't have to import each and every certificate that belongs to another system integrated. See below on how to extract the root and intermediate cert.
Step 2. Installing the certificate
Next is to install the extracted certificate in the keystore, one way is to install it right on the jre's keystore and the more secure way is to setup a local truststore and pass it as JVM parameter (e.g. -Djavax.net.ssl.trustStore=./LocalTrustStore)
1. Import the certificate
keytool -import -alias {THE_ALIAS} -keystore {PATH_TO_KEYSTORE} -file {CERTIFICATE FILE}
Default jre keystore can be found under jre/lib/security directory.
2. Verify it
keytool -list -keystore {PATH_TO_KEYSTORE} -alias {THE_ALIAS}
Step 3. Testing using SSLPoke
Get SSLPoke
here, it's one nice utility to check whether you have successfully import the certificate or not.
java SSLPoke {URL} {PORT}
e.g. java SSLPoke myserver 1234
Reference:
1. https://operational.io/openssl-commonly-used-commands/
2. https://gist.github.com/4ndrej/4547029
2. Extract root and intermediate
openssl x509 -in cert.x509 -text
Find the URL of the signing certificate.
curl (url) >signer.der
Download the signing certificate to a file (DER format in my case).
openssl x509 -inform der -in signer.der -out signer.pem
Convert signing certificate to PEM (X.509) format.
openssl x509 -in signer.pem -text
Confirm your results. Repeat procedure as necessary all the way up the certificate chain.