Sunday, July 25, 2021

How to Fix javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException in Java? Example

If you are working in a Java web or enterprise application that connects to any other web server using HTTPS you might have seen the "javax.net.ssl.SSLHandshakeException". This is one of the particular cases of that error. If you know how SSL and HTTPS work that when a Java client connects to a Java server the SSL handshake happens. In these steps server return certificates to confirm its identity, which the client validates against the root certificate he has in its truststore. If Server returns a certificate that cannot be validated against the certificates a browser or Java client holds in its truststore then it throws the "sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target".

In other words, while connecting to any website or server using SSL or HTTPS in Java, sometimes you may face a problem of "unable to find valid certification path to requested target" exception  as shown below:

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

The reason of this error is simple, certificates returned by the Server during SSL handshake are not signed by any trusted Certification Authority(CA) which are configured in your JRE's truststore e.g Verisign, Thwate, GoDaddy, or Entrust etc.


Instead, the Server is sending a certificate that is unknown to JRE and that's why it's not able to validate those certifications against the private key he holds in his truststore.

If you remember, there is a subtle difference between keystore and truststore in Java. Even though, both stores certificates, keystore is used to store your credential (server or client) while truststore is used to store other credentials (Certificates from CA).

This could also happen when Server is sending certificate from other certificate authority which is not configured in JRE's truststore i.e. some internal certificate signed by your company.


I got the exactly same error while connecting to our LDAP server using SSL from my Spring Security based Java web application. Since LDAP server was internal to the company, it was sending internally signed certificates which were not present in the Tomcat's JRE (Java Runtime Environment).

To solve this problem you need to add certificates returned by the Server into your JRE's truststore, which you can do by using keytool or other tools provided by your company.



How did I solved this Problem?

Nothing fancy, I use an open source program called InstallCert.java to add certificates returned by the Server into my JRE's truststore. I just ran this program against our LDAP server and port. When it first tried to connect LDAP server using SSL it threw same "PKIX path building failed" error and then prints certificates returned by LDAP server. It will then ask you to add Certificate into keystore just give certificate number as appeared on your screen and it will then add those certificate into "jssecacerts" inside C:\Program Files\Java\jdk1.6.0\jre\lib\security folder. Now re-run the program that error should be disappeared and it will print:

"Loading KeyStore jssecacerts...
Opening connection to stockmarket.com:636...
Starting SSL handshake...
No errors, certificate is already trusted

You are done, now if you try authenticating against same LDAP server you will succeed. You can also configure the path of the JRE used by your application e.g. if you are running your application inside Tomcat, then you must give the path to the JRE used by Tomcat. You also need to configure HTTPS in Tomcat, which you do by following steps given here.

Here is also a nice diagram which tells what exactly happens when a Java client connect to Java server using https or SSL i.e during SSL handshake:

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


By the way, this is not the only way to add certificates into the truststore. You can also use the keytool to add certificates into trust store as well. The keytool comes with JDK installation and you can find it inside the bind directory of JAVA_HOME.

This solution is particularly useful when you don't have the certificates used by Server. If you can contact your infra guys or Linux admin to get certificates then you can use keytool to add those into truststore as shown below:

$ keytool -import -alias -ca -file /tmp/root_cert.cer -keystore cacerts

You can see here for some more examples of using keytool command in Java e.g. listing all certificates it has currently etc.

No comments :

Post a Comment