6

I want to build a Spring 3 (v 3.1.1.RELEASE) application (on Java 1.6) to communicate with an HTTPS web service, which is using a self-signed certificate that I created. I'm confused about how to set up my truststores and keystones. Using my self-signed certificate, I generated a keystone using the below commands ...

openssl pkcs12 -export -in server.crt -inkey server.key \
           -out server.p12 -name myalias 

keytool -importkeystore -deststorepass password -destkeypass password -deststoretype jks -destkeystore server.keystore -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass password -alias myalias

Then I configured my Spring application like so …

    <http-conf:conduit name="*.http-conduit">
            <http-conf:tlsClientParameters secureSocketProtocol="SSL" disableCNCheck="true">
                    <sec:trustManagers>
                        <sec:keyStore type="JKS" password="password" resource="server.keystore" />
                    </sec:trustManagers>
                    <sec:keyManagers keyPassword="password">
                        <sec:keyStore type="pkcs12" password="password" resource="server.p12" />
                    </sec:keyManagers>
            </http-conf:tlsClientParameters>
    </http-conf:conduit>

    <jaxws:client id="orgWebServiceClient"
            serviceClass="org.mainco.bsorg.OrganizationWebService" address="${wsdl.url}" />

but when I run my application, I get the below error. What have I missed?

Caused by: javax.net.ssl.SSLHandshakeException: SSLHandshakeException invoking https://nonprod.cbapis.org/qa2/bsorg/OrganizationService: Received fatal alert: handshake_failure
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [classes.jar:1.6.0_45]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) [classes.jar:1.6.0  _45]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) [classes.jar:1.6.0_45]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513) [classes.jar:1.6.0_45]
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.mapException(HTTPConduit.java:1458) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1443) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:659) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262) [cxf-api-2.6.0.jar:2.6.0  ]
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89) [cxf-rt-frontend-simple-2.6.0.jar:2.6.0]
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134) [cxf-rt-frontend-jaxws-2.6.0.jar:2.6.0]
... 5 more
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215) [jsse.jar:1.6]
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) [jsse.jar:1.6]
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) [jsse.jar:1.6]
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) [jsse.jar:1.6]
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014) [classes.jar:1.6.0_45]
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230) [jsse.jar:1.6]
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1395) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1337) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
    at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:42) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69) [cxf-api-2.6.0.jar:2.6.0]
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1415) [cxf-rt-transports-http-2.6.0.jar:2.6.0]
... 15 more
Dave
  • 15,639
  • 133
  • 442
  • 830
  • Hi Dave, we need some more information. So your HTTPS Web Service is running on what application server, Tomcat? Is your spring application running on the same physical server or a separate server? – Hiro2k Jun 28 '13 at 21:51
  • 4
    Can you add this to the JVM args: `-Djavax.net.debug=ssl,handshake,failure` and post the results of the log? – Avi Jun 28 '13 at 22:45
  • Also, you can look at a similar question of mine in which I had the same problem and I posted everything I checked that after a lot of investigation led me to the answer: http://stackoverflow.com/questions/15544116/sslhandshakeexception-received-fatal-alert-handshake-failure-when-setting-ciph – Avi Jun 28 '13 at 22:47

3 Answers3

3

If you are not doing a two-way SSL authentication meaning, your server does not care about who the client is so it does not need to check and verify the client certificate; then in that case all you need on the client side is just a trust store which contains a list of trusted server certificates. In your case, your client truststore would just contain the self signed server certificate and thats all. It is usual practice in java to have your truststore in .jks format. If you manage to generate a the truststore then you are set. On the server side you need not worry about the truststore but need to configure the server to have a valid server certificate.

In a two-way SSL authentication, you need keystore and truststore both configured on both the client and server side . Client truststore would remain same as in the case of 1-way authentication. Server truststore should contain the self signed client certificate. Both client and server should be configured to use their respective certificates which they present to each othe during SSL handshake. During handshake both parties verify each other's certificate against their truststore and establish the opposite party's identity. And once the identities are established then you should be able to establish the connection.

For generating stores I would suggest to use a tool called Portecle which can be quite handy.

Drona
  • 6,886
  • 1
  • 29
  • 35
  • "then in that case all you need on the client side is just a trust store which contains a list of trusted server certificates" What if you are hitting https servers based on user's input dynamically. So you don't know the servers ahead of time. What would you do in that case? – Rose Oct 28 '15 at 04:58
0

Here are the sequence of things you need to check for:

  1. Check for your entry in keystore using keytool -list. Refer this article for syntax
  2. Check if there are a common set of supported cipher suites between your client and server
  3. Finally, point the file to .jks in both keyManagers and trustManagers as mentioned in cxf documentation
Chris
  • 5,584
  • 9
  • 40
  • 58
0

You should have correct SSL certificate in your keystore, of server to whom you are trying to connect.

You can create Keystore using method given here.

Check these examples. These are working for me.

example 1 example 2

Muhammad Imran Tariq
  • 22,654
  • 47
  • 125
  • 190
  • Your certificate should be in the keystore, the certificates of the servers whom you are trying to connect should be either in the trust store or the java cert store. – Raymond Aug 25 '16 at 12:55