Experiencing an error when connecting a Java HTTP client code with a WebSphere server URL. The test throws an SSL handshake error message:
The code deploy was tested with Java7 and Java8:
java -Djavax.net.ssl.keyStore=mykey.jks -Djdk.tls.client.protocols=TLSv1.2 -Djavax.net.debug=ssl,handshake postHTTPWAS
Log file:
..
jdk.tls.client.protocols is defined as TLSv1.2
SSLv3 protocol was requested but was not enabled
.. Extension server_name, server_name: [type=host_name (0), value=myhost.domain.com]
***
main, WRITE: TLSv1 Handshake, length = 155
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
main, SEND TLSv1.2 ALERT: fatal, description = handshake_failure
main, WRITE: TLSv1.2 Alert, length = 2
main, called closeSocket()
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
The java.security settings of the JRE are configured as followed:
...
jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
jdk.tls.disabledAlgorithms=SSLv3
jdk.certpath.disabledAlgorithms=SSLv3
com.ibm.jsse2.disableSSLv3=true
Questions:
1) Why does the SSL trace show a reference to SSLv3, a protocol that was logically disabled at the client security setup?
2) What is the root error of the SSLHandshakeException?
3) Is it possible to enable TLSv1.2 as a default choice for all HTTPS client connections and which is the right system property to set it?
I've isolated the error.
The newer releases of WAS application server (full) expect that the client will connect with TLSv1.2. For manual Java JRE invocation use the parameter -Dhttps.protocols=TLSv1.2, shown below:
/opt/java8/ibm-java-x86_64-80/bin/javac SSLTest.java && /opt/java8/ibm-java-x86_64-80/jre/bin/java -Dhttps.protocols=TLSv1.2 SSLTest
For Apache HTTPS clients (> V.4.5.2), I added a few additional sections, to get the HTTPS connected with TLSv1.2. Both connections now are working OK.
// for TLSv1.2 add:
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;
import org.apache.http.ssl.SSLContexts;
//Set the https use TLSv1.2
private static Registry<ConnectionSocketFactory> getRegistry() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext sslContext = SSLContexts.custom().build();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
}
// for TLSv1.2 use:
PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(getRegistry());
clientConnectionManager.setMaxTotal(100);
clientConnectionManager.setDefaultMaxPerRoute(20);
HttpClient client = HttpClients.custom().setConnectionManager(clientConnectionManager).build();