Search code examples
javasslhttpclient

How SSL Handshaking works in Java 7 vs Java 8


Recently while working with HttpClient for accessing 3rd party service (CURL Service) in Java application, I came across problem like:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
....

I got this problem in JDK 7. With some research on this problem I found 2 suggestions i.e.

  • Add certificate of that particular 3rd party in your JDK 7 Truststore. [Which I tried but still got same issue]
  • Use JDK 8 instead of JDK 7 [Which I tried and it worked for me]

So I am trying to understand like how SSL Handshaking takes place in Java 8 as compare to Java 7 or lower? And I can fix this issue in JDK7

Code Snnipet

public String getProduct(final String accessToken) throws IOException, ParseException {

    log.info("accessToken: " + accessToken);
    final String stringUrl = "https://api.molt.in/v1/products";
    HttpClient httpClient = HttpClientBuilder.create().build();
    HttpGet getRequest = new HttpGet(stringUrl);
    getRequest.setHeader("Authorization", "Bearer " + accessToken);
    HttpContext httpContext = new BasicHttpContext();
    HttpResponse response = httpClient.execute(getRequest, httpContext);
    log.info("Response Code : " + response.getStatusLine().getStatusCode());

    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    StringBuffer result = new StringBuffer();
    String line = "";
    while ((line = rd.readLine()) != null) {
        result.append(line);
    }
    log.info("result: " + result);

    rd.close();
    return result.toString();
}

~Regards,

Chandan


Solution

  • The server closes the handshake because the client uses an unsupported protocol. See this question, where it's suggested to launch Java 7 with:

    -Dhttps.protocols=TLSv1.1,TLSv1.2
    

    You'd get an error from your client (javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed) if the server certificate were not trusted, and it works this way: the Java client checks the server's certificate to be sure that the machine it is talking to is actually who it claims to be, in your example "api.molt.in". The check works like this:

    • if the certificate is self signed, it is trusted if found in the default trust store
    • if the certificate is signed by an authority, it is trusted if the authority's certificate is found in the default trust store.

    The list of trusted parties may be updated in every Java minor release. For example certificates generated with Let's encrypt are only trusted by Java 8 since the 101 update.