Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLS

6.2k views Asked by At

With Java 8, server which only supports TLSv1, it fails to make secure socket connection from cent OS

Version

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

Source

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by jigar.joshi on 6/10/15.
 */
public class SSLTester {
    public static void main(String[] args) throws Exception {
        SSLSocketFactory f =
                (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket socket = (SSLSocket) f.createSocket("efm.sandbox.vovici.com", 443 );
        try {
            printSocketInfo(socket);
            socket.startHandshake();    
            System.out.println("----------------------------------SUCCESS----------------------------------");

            BufferedReader r = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
            String m = null;
            while ((m = r.readLine()) != null) {
                System.out.println(m);

            }
            r.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println(e.toString());
        }
    }

    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: " + s.getClass());
        System.out.println("    Remote address = "
                + s.getInetAddress().toString());
        System.out.println("    Remote port = " + s.getPort());
        System.out.println("    Local socket address = "
                + s.getLocalSocketAddress().toString());
        System.out.println("    Local address = "
                + s.getLocalAddress().toString());
        System.out.println("    Local port = " + s.getLocalPort());
        System.out.println("    Need client authentication = "
                + s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("    Cipher suite = " + ss.getCipherSuite());
        System.out.println("    Protocol = " + ss.getProtocol());
    }

}

With same version of JVM, it makes handshake successfully on OSX, it fails on centOS, Failure reason is it only tries to use TLSv1.2 (default in JVM 8) and doesn't try lower protocol

debug notes:

-Ddeployment.security.TLSv1.0=true 

-Ddeployment.security.TLSv1=true 

-Ddeployment.security.TLSv1.1=false 

-Ddeployment.security.TLSv1.2=false 

-Djavax.net.debug=ssl:handshake:verbose 

Question:

  • Why it is able to choose TLSv1 on OSX and not on CentOS?

  • How can I tell JVM to use protocols in specific order or if it considers order by the version then how can I tell it to also try with v1

Edit:

I have unlimited strength JCE policies installed with JRE that is causing this, it works without that so OSX and CentOS difference is gone, How can I still make it work ?

Edit:

Output

Socket class: class sun.security.ssl.SSLSocketImpl
    Remote address = efm.sandbox.vovici.com/206.132.29.15
    Remote port = 443
    Local socket address = /10.10.152.143:50376
    Local address = /10.10.152.143
    Local port = 50376
    Need client authentication = false
    Cipher suite = SSL_NULL_WITH_NULL_NULL
    Protocol = NONE
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1529)
    at sun.security.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1541)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
    at SSLTester.main(SSLTester.java:24)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
    at sun.security.ssl.SSLSocketImpl.getSession(SSLSocketImpl.java:2225)
    at SSLTester.printSocketInfo(SSLTester.java:56)
    at SSLTester.main(SSLTester.java:23)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961)
    ... 5 more
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
1

There are 1 answers

0
YuriK On BEST ANSWER

Try limiting the protocols to just TLSv1 using:

-Djdk.tls.client.protocols=TLSv1

See this page for more details: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2

Hope this helps,

Yuri