8 Replies Latest reply: Jun 11, 2011 8:26 PM by EJP RSS

    Problem connecting to HTTPS host with self signed certificate

    800533
      I have set up a tomcat server with SSL running in a vmware on my machine using a self signed certificate. I can connect to this no problem with a browser from my main machine with the url https://myserver:8443.

      However, I am not able to connect with a Java client. I always get the below exception. I read that I need to add it as a trusted certificate in the keystore. I went to the site with firefox and saved the certificate as a .cer file, and imported it into the default keystore at c:\users\louis\.keystore. I still have the same problem. I think the problem is the client is not using the keystore, and I don't know how to make it do so. I tried adding the following argument to the run command:

      -Djavax.net.ssl.trustStore=c:\users\louis\.keystore -Djavax.net.ssl.trustStorePassword=changeit

      but it doesn't help.

      Here is the exception I'm getting:

      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
           at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1611)
           at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
           at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
           at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035)
           at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124)
           at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
           at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1139)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)
           at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
           at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
           at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
           at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
           at Test.main(Test.java:39)
      Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
           at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:285)
           at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191)
           at sun.security.validator.Validator.validate(Validator.java:218)
           at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
           at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
           at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
           at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014)
           ... 12 more
      Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
           at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
           at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
           at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280)
           ... 18 more
        • 1. Re: Problem connecting to HTTPS host with self signed certificate
          EJP
          Your client's truststore doesn't trust your server's keystore. You have to export the self-signed certificate from the server's keystore and import it into your client's truststore. Believe me it is far simpler to pony up the $50 or whatever it is and get a CA-signed SSL certificate for the server.
          • 2. Re: Problem connecting to HTTPS host with self signed certificate
            800533
            Didn't realize it was that cheap, but I still don't really want to do that just for early testing, since that cert won't be used in the final product anyway.

            The server is running in a vmware, so it's effectively on a separate machine and has it's own keystore. I created a new keystore for the client, went to the site with a browser and saved the cert to a file, and then imported that to the client's keystore.
            • 3. Re: Problem connecting to HTTPS host with self signed certificate
              EJP
              and then imported that to the client's keystore.
              Wrong. You need to import it into the client's truststore.
              • 4. Re: Problem connecting to HTTPS host with self signed certificate
                800533
                I am importing it as a trusted cacert into the keystore. I haven't read anything about a trust store that is separate from the keystore.
                • 5. Re: Problem connecting to HTTPS host with self signed certificate
                  EJP
                  You've read it here. I've said it several times. You should also have read it in the JSSE Reference Guide.
                  • 6. Re: Problem connecting to HTTPS host with self signed certificate
                    800533
                    I have worked around this problem by configuring the Java client to trust all certificates and disabling hostname verification. That way I don't need a trust store. I'll just have to remove that code in production. Not ideal since I'd rather have certificate/hostname verification working for testing, but it works at least.

                    I have looked at the Java security documentation and as far as i can tell a keystore and trust store is still basically the same type of file and created the same way with the keytool. The difference is when you import a cert you use the -trustcacerts option. The client 'keystore' is only being used to store the trusted cert, so it essentially is a trust store. This is documented in the keytool doc for the command -importcert.

                    http://download.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html

                    I actually think my problem is more to do with the hostname, since my server doesn't have a real domain hostname like www.myserver.com. I am just using the machine name for the host, although web browsers do not have a problem with this. When I set my java client to trust all certs, I was getting the following error:

                    java.io.IOException: HTTPS hostname wrong

                    Disabling hostname verification fixed this, so I'm wondering if my cert has the wrong hostname. I originally created the self signed cert using the keytool with the command -genkey, which creates a key pair and also a self signed cert. I looked at the keytool docs, and I don't see any way of specifying the hostname or even seeing what the host name of a cert is. What does it put as the hostname by default? The IP address or machine name, or am I understanding this wrong?
                    • 7. Re: Problem connecting to HTTPS host with self signed certificate
                      800533
                      Ok this is now solved.

                      I found out that the common name field of the certificate has to be the hostname. Keytool threw me off because it asked me to put my first and last name for that field.

                      Also, you were right, I need to specify that it's the truststore, not keystore. I changed the VM arguments to this:

                      -Djavax.net.ssl.trustStore=c:\users\louis\.keystore -Djavax.net.ssl.trustStorePassword=changeit
                      • 8. Re: Problem connecting to HTTPS host with self signed certificate
                        EJP
                        That's a requirement for HTTPS but it doesn't cause the exception you posted above. That exception was resolved by getting the keystore and truststore correct. Hostname verification happens at a later phase and causes a different exception.