"Received fatal alert: handshake_failure" when trying to connect to https web service
Asked Answered
T

3

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
Twiddle answered 14/5, 2013 at 21:48 Comment(3)
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?Noto
Can you add this to the JVM args: -Djavax.net.debug=ssl,handshake,failure and post the results of the log?Nitz
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: #15544616Nitz
D
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.

Disseminule answered 5/7, 2013 at 8:58 Comment(1)
"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?Handtomouth
P
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
Paramedical answered 3/7, 2013 at 18:23 Comment(0)
G
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

Gondar answered 5/7, 2013 at 7:33 Comment(1)
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.Embryologist

© 2022 - 2024 — McMap. All rights reserved.