简体   繁体   中英

Java SSL handshake failure

This question is a continuation of my rather off-topic and unclear question here .

Recently I've been working with SSLSockets, and no matter what I do, I keep getting the following error:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at com.gmail.socraticphoenix.plasma.net.client.ClientThread.run(ClientThread.java:72)

As of right now, I'm using a TrustManager that trusts all certificates (for testing purposes), and it looks like so:

public static TrustManager[] getAllTrusting() {
    return new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            }
    };
}

The code for creating the listener socket is:

    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, NetUtility.getAllTrusting(), new SecureRandom());
    SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
    SSLServerSocket socket = (SSLServerSocket) factory.createServerSocket(this.server.getPort());
    socket.setUseClientMode(false);
    socket.setSoTimeout(500);

The code for the client socket is like so:

    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, NetUtility.getAllTrusting(), new SecureRandom());
    SSLSocketFactory factory = sslContext.getSocketFactory();
    SSLSocket socket = (SSLSocket) factory.createSocket(this.client.getTargetHost(), this.client.getTargetPort());
    socket.setUseClientMode(true);
    socket.startHandshake();

I've tried setting the protocol, enabling and disabling session creating, and setting cipher suites. I'm pretty much stumped. The full debug trace is on pastebin .

Also, as a note, when I replace the listener and client code with regular, insecure sockets, the test class outputs the expected result, meaning that that code is where the problem lies.

TL;DR handshake_failure, please help!

Edit 1: To clarify, the server and client are running on the same JDK, on the same machine.

From the debug output it is visible that

  • The client supports only a single cipher: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. Since this ciphe is a TLS 1.2 cipher the client will not support TLS 1.0 or TLS 1.1.
  • The server answers with a TLS alert to the ClientHello, thus ending the handshake with a fatal error.

The alert from the server means it does that it cannot continue with the handshake. The exact reason for this is not contained in the alert but you might see it in some log files at the server side. My guess is that the server simply does not support this single cipher which is accepted by the client.

While I'm not familiar with dealing with such problems in Java I would suggest that you simple throw out all your code which uselessly restricts the client to this single cipher. By default Java should support much more ciphers and thus cause less problems. If the problem continues look at the server side for more information why the server does not accept the client.

Thanks for everyone's help, but the following is my solution:

In the listener thread, where I create the server socket, I pass in null for keymanagers in SSLContext.init() . This causes the server to not be able to respond to the client, and as such causes a handshake error (which was pointing to unsupported cipher suites, but was actually caused by the null keymanagers). Creating and loading a KeyManager with KeyManagerFactory has fixed the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM