Search code examples
javaperformancessltls1.2httpsurlconnection

How to accelerate tls negotiation in JAVA?


There'a a private web server(https supported) on which i need to read/set some information frequently. I made some java code to do it automatically. When I use Chrome to access it, the first connection is slow(maybe 5 seconds) but the continuous connection is fast(about 1S). With my java code, it is slow everytime. I know the problem is that full TLS handshake is performed in every connection with my code. My question is, what does Chrome do to make it fast and how can i simulate it in my code? Below is part of my code:

    class MyTrust implements X509TrustManager{
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public X509Certificate[] getAcceptedIssuers() {return null; }   
    }

and in another class where connection is established:

    URLConnection conn = (HttpsURLConnection) url.openConnection();
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, new TrustManager[] { new MyTrust() }, new java.security.SecureRandom());
    ((HttpsURLConnection) conn).setSSLSocketFactory(sc.getSocketFactory());

I'm reading Java Secure Socket Extension (JSSE) Reference Guide but find it's difficult to understand. Is it SessinID or Principal that works? Can anyone give me some hints?


Solution

  • Your java code establish a connection every time, so a TLS handshake is performed every time.

    But browsers(such as Chrome) will try to keep the connection alive(by add a Connection:Keep-Alive header in requests), if the server accepts keep-alive connection(by returning a Connection:Keep-Alive header in the response), which most servers do, the browser will try to use this same connection on ongoing requests, thus won't need to perform TLS handshake everytime.

    For your java code, you can store the connection in a pool, and reuse it. You can check Apache HttpComponents, which support http connection pooling

    Edited from comments:

    Since the real problem is about SSL/TLS session reuse not working. I suspect it is caused by misuse of JSSE. You must use same SSLContext on each connection to enable session reuse. Further more, the session could be discarded due to some wrong operations on the connection(such as reading past the end of the stream). There are some details listed here: How to enable client TLS session reuse in Java