Hopefully this might help someone out, because 99% of the hits that come up when googling this java error bring you to someone telling you how to bypass certificate verification when testing with self-signed or other bad certificates. But if you’re getting this error from a website that seems to have a good certificate (e.g., you can go there with your browser and it doesn’t complain), then here’s a possible explanation.
In my case, it turns out that the problem is with the intermediate certificate in the cert chain. If you examine the certificate in your browser, you can see the entire chain. Well, the intermediate cert in the chain had a
"CN = VeriSign Class 3 International Server CA - G3". Presumably most browsers have this cert in their keystore already, and therefore don’t complain that the cert is invalid. But the java installation I was using did not have this cert, and therefore couldn’t build the certificate chain.
To see that more closely, I put on ssl debugging by adding
-Djavax.net.debug=ssl when starting the JVM, and the root error said
"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". This is at least better than “peer not authenticated”.
You can also go to verisign and use their certificate checker here. In the java applet they have there, put in the server name with the certificate in question. In my case, it did indeed report a status of “Invalid Chain”.
So even verisign’s own checker did not recognize the chain as valid due to the missing intermediate cert. The webserver should actually supply the intermediate cert along with its own cert, and then the client can verify it because the root cert (in this case, “VeriSign Class 3 Public Primary Certification”) pointed to by the intermediate cert is by default recognized by java.
So what to do? Well, really, the administrators of the webserver should fix the configuration so that the entire chain is valid. But barring that, if you really must get around the error and don’t want to use the dummy trust manager (which you should of course not do in a production environment), you can import the intermediate certificate into your java installation’s keystore. Export it using your browser (make sure you export the offending intermediate cert), then import it into your java keystore like so:
cd C:\Program Files\Java\jre6\lib\security
keytool -import -file "C:\VeriSignClass3InternationalServerCA-G3.crt" -keystore cacerts
“cacerts” is the file that contains all the trusted certificates for the java installation. You can verify which cacerts file your java installation is using by using the aforementioned JVM switch to debug ssl (
-Djavax.net.debug=ssl), it will display the trustStore it is using. The filename “C:\VeriSignClass3InternationalServerCA-G3.crt” is what I exported from my browser.