When your Java program attempts to connect to a server that has an invalid or self signed certificate, such as an application server in a development environment, you may get the following exception:
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
To make your Java runtime environment trust the certificate, you need to import it into the JRE certificate store.
Step 1 - Get the certificate into your browser store
Browse to your application server using SSL. Your browser will tell you that the certificate isn't trusted and allow you to trust it, thereby placing it in the browser certificate store.
Step 2 - Export the certificate to a binary file
Your browser will have some kind of certificate manager that allows you to export or back up specific certificates to binary files. In Firefox that would be under Preferences / Advanced / Encryption / Servers. Find the certificate presented by the server and export it as a binary DER file.
Step 3 - Import the certificate into the Java Store
Make sure you have write access to your JRE and use the keytool utility to import it:
keytool -import -alias alias -keystore path-to-jre/lib/security/cacerts -file path-to-certificate-file
Example:
keytool -import -alias sunas -keystore /opt/jdk1.6/jre/lib/security/cacerts -file /home/gugrim/tmp/sunas.der
You will be prompted for the keystore password, which is by default changeit.
Also, when you connect to the server make sure you use the same name as the one set as the Subject in the certificate. You may need to add it to your host file if the server isn't reachable using this name, which may be the case for a developer server.
That's it!
- Log in to post comments
Nice post really helpful
thanks for your post it really helpful
great great great
Really great post and thanks .you almost save my life.
Thanks
Thanks a lot Boss.........
Nice precise steps
I would like to add that in windows the folder permissions of the path-to-jre/lib/security needs to have read/write permissions. Apparently just changing permissions of cacert file is not sufficient
Very helpful
Thanks for the helpful information - was stuck on where to place the trusted certificate but following these steps it worked :)
THANKS
Your covered all important steps nice and clearly in a brief way! Thanks a lot, it helped me a lot :)
Thanks
Hey Its so simple, Thanks..:-)
Very helpful and clear
Thanks a lot. It is really helpful and very clear.
Helped a lot !
Hey, Nice post. Simple and clear to follow. Thanks
Thanks
Thanks for the useful information.
I got similar problem and thus came into this page.
I had a self signed certificate on mail server and the client gave similar exception.... SunCertPathBuilderException: unable to find valid certification path to requested target
I struggled many ways... like import the certificate to the keystore ..still it did not worked.
At last used the below single line of code, and it solved the problem.
props.put("mail.smtp.ssl.trust", <mail server host>);
Cheers
Jay
Good information
Easy to understand, i was looking for a java program to import the certificate, is that possible ?
Great help
Thanks for nice post, works well.
+1 and number one on google :)
Even though the page is a little older, the info still works great - so that is why google decided to make you the first result i gues! +1!
thanks
Nice help
This is a really helpful post.
Helpful
Thanks so much..this was very helpful to me.
Excellent steps
The steps metioned here is absolutely correct and most helpful. Thank you very much.......
Very helpful
Thank you so much :)
thank you
thank you
Cert on JRE
You solve my problem. Great !
THANK YOU
It perfect working on Windows environment.
Just one note: CMD must be "Run as Administrator" to process command
Thank You
Very Helpful
Very useful. I am using my java client to connect to my Web service with custom SSL certificate. This is perfect to add a client certificate on my JVM.
Another way which I was using since I have the jks with me to pass on the jvm parameters-
-Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/path/ks-name
-Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/path/ts-name
Very helpful
Thanks a lot ..its working as expected....
Its worked
Hi, thanks for the share. It helped me to add the certs to cacerts.
keytool -import -alias exacttarget -trustcacerts -keystore "C:\Program Files\Java\jdk1.7.0_131\jre\lib\security\cacerts" -file "D:\downloads\thirdservice.der"
D
thank you man
Thank you
Extremely thankful to you brother
Thank you
Many thanks, it worked for me.
I'll pile on -- Thanks!
Just the right detail, exactly what is needed. I'll add "restart the JVM."
How to restart JVM?
I don't want to restart the server machine. Is there any way to restart just the JVM?
Just restart the application
Just restart the application server you are using, e g Wildfly, GlassFish or whatever. No need to restart the machine.
THANKS!
Thanks. keep on sharing
Sorry it might be very basic
Sorry it might be very basic question but I am new to this. But I have performed all steps as mentioned in the post but still getting SSLHandshake error. Can anyone please help me on statement? I am calling an API using httpClient, how to mention subject name in my request. Any sample code would be helpful.
"when you connect to the server make sure you use the same name as the one set as the Subject in the certificate. You may need to add it to your host file if the server isn't reachable using this name, which may be the case for a developer server"
See my reply to your question
See my reply to your question below, HTH.
Elaborate Subject in the certificate and host file
when you connect to the server make sure you use the same name as the one set as the Subject in the certificate. You may need to add it to your host file if the server isn't reachable using this name, which may be the case for a developer server.
Please elaborate it. Any code snippet would be helpful.
Subject and hosts file
The subject in the certificate is the name of the server. The server must be accessed using this name for the certificate check to pass. If the subject is e g "mypc" your code should connect to the server using this name. If it were to use e g "localhost", the certificate would be denied. The hosts file could contain a line like
127.0.0.2 mypc
and you connect with an URL using this name, e g
HttpURLConnection con = (HttpURLConnection)(new URL("https://mypc:8080/myapp").openConnection());
thank you
concise and useful !!!
thank you