If you are working in Java web or enterprise application which connect to any other web server using HTTPs you might have seen the " javax.net.ssl.SSLHandshakeException" . This is one of the particular case of that error. If you know how SSL and HTTPS works that when a Java client connect to a Java server the SSL handshake happens. In this steps server return certificates to confirm it's identity, which then client validates against the root certificate he has in its truststore . If Server return a certificate which 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:
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 Server during SSL handshake is not signed by any trusted Certification Authority(CA) which are configured in you JRE's truststore e.g Verisign, Thwate, GoDaddy, or Entrust etc.
Instead, Server is sending a certificate which is unknown to JRE and that's why it's not able to validate those certifications against the private key he hold 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 others credential (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:
By the way, this is not the only way to add certificates into 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 cacertsYou can see here
for some more examples of using keytool command in Java e.g. listing all certificates it has currently etc.