javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated – even with seemingly valid certificate

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.

About these ads
This entry was posted in Uncategorized and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s