Reputation: 556
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.
Upvotes: 0
Views: 7448
Reputation: 556
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.
Upvotes: 0
Reputation: 123260
From the debug output it is visible that
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.
Upvotes: 2