Why does a signed certificate give me a handshake failure using Java? - java

I am accessing a web service. When I go to the web service's URL in my browser, the certificate is signed and automatically is accepted.
What I don't understand is that when I use Java to access the web service I get something along the lines of:
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
I would imagine this means that the certificate is not signed, but it is.
Doesn't com.sun.net.ssl.internal.ssl go to the certificate authority automatically and check if the certificate is signed? If not, is there something I need to set up in addition in order to do this?

There is more checking than just the signature. The certificate authority that produced the signature must be validated, among other things. Java's list of trusted certificate authorities is different than your browser's. You may need to download the CA cert with your browser and install it with Java's keytool.

It seems that the web server or the URL you are connecting to does not have a valid certificate from an authorized CA.To solve see this alternative solution.

Related

Is it possible to disable ssl for https?

Application on java. OkHttp version 2.7.5 is used. A request is made to another service and an error occurs.
SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
I do not have a certificate. It seems there are solutions for the version of okHttp3. But the version can not be changed. How to solve a problem?
Is it possible to disable ssl for https?
Literally, no.
Use of SSL is fundamental to the HTTPS protocol. If you don't want to use SSL at all, configure your server with an HTTP endpoint and use that instead of HTTPS.
Furthermore use of SSL requires a certificate that is (at least) syntactically well-formed. That is also fundamental to the HTTPS protocol.
Now if the problem is that your server certificate has expired, then a possible solution is to use the approach described in:
Make a connection to a HTTPS server from Java and ignore the validity of the security certificate.
And if the problem is that you cannot get a proper certificate for the server (e.g. you can't afford it) then an alternative solution is:
generate a self-signed certificate; see How to generate a self-signed certificate using Java Keytool,
install it on the server side,
configure the client as above to ignore certificate validity.
But note that doing either of those things has security issues.
There is a third solution that is more secure.
generate a self-signed certificate (as above)
install it on the server side,
use Keytool to add the certificate to the client app's keystore as a trusted certificate.

Calling SSL URL from Java gives certificate issues

I'm trying to do an API using SSL. When I perform the call, I get the following error:
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://yyyyy.zzz/123":sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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
I know there are many questions in StackOverflow regarding this issue, but the ones I saw was because certificate was self-signed. In this case certificate is valid and browser recognize it without problems as a valid one.
So my question is, why does it fail when calling from Java and it does work well when using the browser?
I had same issue. The browser recognized the certificate (and certificate path), but Java Virtual Machine did not. The error text was the same.
In my case the trust root was in Browser keystore, and in Java trust keystore. So everyone could check thrust path. But if your server returns not the whole certificate path, but only server one, it is harder. In this case, the certificate path could be validated only if validator has the INTERMEDIATE certificate in its thrust-store.
Because the java keystore is not updated as regularly as these in browsers, you could have the intermediate certificate in browser, but not in JVM.
Possible solutions in this case:
server to return the whole certificate chain
the intermediate certificate to be added in java trust store
For more info check Certificate path discovery in Java

Java mail TLS authentcation

I am trying to get a grasp on the fundamentals of Java Mail API and TLS. I have the following scenario:
There is an STMP server that uses TLS & SSL. If I log on to this server with some client, I can send authenticated &verified e-mails without any problems.
Then I try to run a web server on a different machine, that sends mail using the previously mentioned SMTP server. I still want to send TLS & SSL emails, however no matter how I configure the startup properties I get the following well known error:
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
I found a lot of people having similar issues, however my question is this:
Considering the previuosly described scenario, do I have to get some kind of certificate to the web server (possible somewhere in the JRE), or should it just work fine since the mail server already has that certificate & authentication mechanizm running. Shouldn't it be possible to just use the certificate of the SMTP server? Anyway, if I have to install the certificate to the machine that uses the STMP server how can I get that certificate?
I'm pretty new to JavaMail API and I have seen lots of articles about this but I could not find the answer black & white for my question.
Your client (that is in your case the one running on the webserver) needs to verify the SSL certificate of the mail server. It seems that your java truststore doesn't contain that certificate.
So you either need to put that certificate into the default truststore of your JRE (what I wouldn't recommend) or define a different truststore for your application (that of course needs to contain the mail servers certificate). To do that set this VM parameter: Djavax.net.ssl.trustStore=<path-to-truststore>
Edit: Ah I missed some part of your question.
To get the certificate of the mail server use something like openssl. See for example:
https://serverfault.com/questions/139728/how-to-download-ssl-certificate-from-a-website
The answer is in the JavaMail FAQ.
Quoted text from the linked site:
Q: When connecting to my mail server over SSL I get an exception like "unable to find valid certification path to requested target".
A: Your server is probably using a test certificate or self-signed certificate instead of a certificate signed by a commercial Certificate Authority. You'll need to install the server's certificate into your trust store. The InstallCert program will help.
Alternatively, you can set the "mail.protocol.ssl.trust" property to the host name of your mail server. See the javadocs for the protocol provider packages for details.
Other common causes of this problem are:
There's a firewall or anti-virus program intercepting your request.
There's something wrong in your JDK installation preventing it from finding the certificates for the trusted certificate authorities.
You're running in an application server that has overridden the JDK's list of trusted certificate authorities.

Steps to trouble shoot SSL

I am trying to trouble shoot a two way SSL handshake mechanism. I get an error
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
This indicates that one of my keystore or my truststore files does not have the appropriate entries. I know the way to trouble shoot this is to go to the server's truststore do the keytool list check the signing authorities and come to the client's key/truststore and verify this.
Can someone list these steps clearly (with the appropriate commands) please? Googling is not leading me anywhere. I just need a list of steps of "How can I confirm that Client X can talk to Server Y with two way SSL using Cert Z"?
The SunCertPathBuilderException exception is thrown whenever there the certificate validator fails to establish a chain between the certificate and a root certificate.
The easiest way to confirm that the certificate validates is to use a graphical tool like
Keyman, or
KeyTool IUI
The above tools are recommended since the exception is usually thrown in the absence of a root certificate.
If you want to examine what certificates are getting exchanged, it is better to switch on the ssl debug flag on the JVM node where the validation is failing.
Another option is to use a network traffic capture utility like Ethereal or Microsoft Netmon to obtain a dump of the traffic containing the certificate exchanges.
PS: Are you using the right keystore in the first place? I remember doing the same mistake many moons ago...

Unable to authenticate to SSL site in java: "pathLenConstraint violated - this cert must be the last cert in the certification path"

I'm trying to read from a secure (i.e. SSL) web page, in Java code.
I'm trying to use both URLConnection (java.net) and Apache's HTTPClient.
In both cases, when I make the request, I get this exception:
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path validation failed:
java.security.cert.CertPathValidatorException:
basic constraints check failed:
pathLenConstraint violated - this cert
must be the last cert in the
certification path at
com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518)
at
com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at
com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at
com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
at
com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at
com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at
com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:818)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1041)
at
sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
at
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:934)
at
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at
com.sap.river.coghead.rest.Main.testJavaHTTPConnection(Main.java:45)
at
com.sap.river.coghead.rest.Main.main(Main.java:32)
Caused by:
sun.security.validator.ValidatorException:
PKIX path validation failed:
java.security.cert.CertPathValidatorException:
basic constraints check failed:
pathLenConstraint violated - this cert
must be the last cert in the
certification path at
sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:187)
at
sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:139)
at
sun.security.validator.Validator.validate(Validator.java:203)
at
com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at
com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at
com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 13 more Caused by:
java.security.cert.CertPathValidatorException:
basic constraints check failed:
pathLenConstraint violated - this cert
must be the last cert in the
certification path at
sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139)
at
sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316)
at
sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178)
at
java.security.cert.CertPathValidator.validate(CertPathValidator.java:206)
at
sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182)
... 18 more
Note that I've succeeded in establishing a non-ssl connection, to a different host though.
I'm also able to view this page using the browser - the certificates are validated correctly there.
Do you I need to somehow change the order of certificates as they are retrieved from the server?
Is there some configuration I'm missing?
Thanks in advance,
Lior
I dug in further and the answer lies in the fact that I needed to import the necessary certificates into the keystore used by the JVM to authenticate SSL.
The key store is the 'cacerts' file under the jre/lib/security folder in the jre that is used to run the program.
I manually exported the site's certificates - all of them.
Then I imported it into my default keystore using the 'keytool' utility provided by Sun. Note that you have to import them in the correct order.
I then put the new keystore instead of the JRE's one - and it worked.
I guess it would've been better to import the certificates directly to the JRE's keystore, but the tool asked me for a password which i didn't know.
I believe there's also a way to program around this more easily, just haven't found it yet. I'll be happy to get some pointers (TrustManager class in JSSE?).
Finally, some credit. This post here: http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html helped to point me in the right direction.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at
pathLenConstraint
see (Note about certificate chains) in
http://groups.google.com/group/google-checkout-developers-forum/web/google-checkout-and-ssl-certificates?version=49
google says it may be problem with certificate chain order, I have just found that my cert is not in order, not fixed yet, working on it. I will update this later.
old post:
Have almost the same problem.
Adding certificate manualy to keystore helps, but I'd prefer to do it more automatically, with my client.
So my solution:
I will use keystore just for this one app, and one host
1. keystore does not exist - create with some generated password
2. save password in config file
3. ask user (or dont) whether he wants to accept this certificate
4. if so - save it to keystore, and use it when needed
Is this a good solution? Any comments?
The problem was with certificate chain order.
It was: A->C->B, but should be A->B->C, once we fixed chain order the application started to work.
I havent personally fixed the certs. but this post was helpful
http://groups.google.com/group/google-checkout-api-troubleshooting/browse_thread/thread/99862c11d37d3127

Categories