Search code examples
javasslapache-commons-httpclient

HTTP Apache, ssl authentication does not work in Java 1.8


The following code works perfectly fine in Java (runtime) 1.6. and 1.7, but it yields: peer not authenticated exception in 1.8. It is compiled in Java 1.6.

It useses apache's httpcore (v4.0.1) and httpclient (v4.0). Any clues why is that? Or should I rewrite it to httpclient 4.5? Does anyone can provide an example?

private InputStream getStreamFromHttps(String url) throws HttpException {
        HttpParams httpParams = new BasicHttpParams();

        HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
        HttpConnectionParams.setSoTimeout(httpParams, 15000);

        DefaultHttpClient httpclient = new DefaultHttpClient(httpParams);

        try {

            KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
            InputStream instream = trustKeyLocation.getInputStream();


            try {
                trustStore.load(instream, trustKeyFilePassword.toCharArray());
            } finally {
                instream.close();
            }

            SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
            Scheme sch = new Scheme("https", socketFactory, 443);
            httpclient.getConnectionManager().getSchemeRegistry().register(sch);
            HttpGet httpget = new HttpGet(url);

            HttpResponse response = httpclient.execute(httpget);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return null;
            }

            BufferedInputStream responseStream = new BufferedInputStream(
                    response.getEntity().getContent());

            return responseStream;
        } catch (Exception ex) {
            throw new HttpException("Https acces failed", ex);
        }
    }

@Warren - thanks for linking related question I will try to go through it today. Here is the stack trace. I haven't posted it before, because it looks like something is wrong with the certificate. So it might be missleading IMO.

Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431) ~[na:na]
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:339) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) ~[httpclient-4.0.jar:4.0]

@Warren - I have subclassed SSLSocketFactory and .setEnbaledProtocols(...) as in the linked questions, but to now avail.

Then I have enabled "javax.net.debug", "ssl:handshake:verbose" and got

Java 1.7

10:35:57.995 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.connection.timeout': 30000
10:35:57.995 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.socket.timeout': 15000
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(15000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1443515758 bytes = { 189, 94, 204, 7, 214, 235, 42, 74, 179, 234, 136, 224, 40, 90, 63, 198, 138, 212, 83, 2, 140, 99, 151, 102, 220, 2, 54, 129 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
main, WRITE: TLSv1 Handshake, length = 149
main, READ: TLSv1 Handshake, length = 1583
*** ServerHello, TLSv1
RandomCookie:  GMT: -567721376 bytes = { 134, 214, 213, 200, 86, 83, 10, 155, 219, 85, 187, 15, 221, 196, 224, 101, 228, 139, 220, 255, 63, 254, 39, 179, 226, 24, 50, 189 }
Session ID:  {}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
*** Certificate chain

Java 1.8

10:34:39.056 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.connection.timeout': 30000
10:34:39.056 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.socket.timeout': 15000
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(15000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1443515679 bytes = { 0, 208, 71, 217, 206, 77, 79, 188, 232, 167, 31, 200, 170, 23, 75, 73, 232, 211, 86, 236, 96, 4, 73, 82, 173, 88, 241, 128 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
main, WRITE: TLSv1 Handshake, length = 151
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1.2 ALERT:  fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
main, IOException in getSession():  javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
main, called close()
main, called closeInternal(true)
10:34:39.203 [main] DEBUG o.a.h.i.conn.DefaultClientConnection - Connection shut down
main, called close()
main, called closeInternal(true)
10:34:39.203 [main] DEBUG o.a.h.i.conn.SingleClientConnManager - Releasing connection org.apache.http.impl.conn.SingleClientConnManager$ConnAdapter@a3ec6b

Solution

  • It looks like I have an answer. I didn't have to enforce TLSv1, but I had to add one of ciphers which are unsupported in JDK1.8, namely:

    SSL_RSA_WITH_RC4_128_SHA or SSL_RSA_WITH_RC4_128_MD5.

    Here is the code. The class implementing these methods extends SSLSocketFactory

    @Override 
    public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { 
        SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        sslSocket.setEnabledCipherSuites(newCiphers);
        return sslSocket;
    
    } 
    
    @Override 
    public Socket createSocket() throws IOException { 
        SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket();
        sslSocket.setEnabledCipherSuites(newCiphers);
        return sslSocket;
    } 
    

    newCiphers var is a String[] of ciphers.