1

I'm working on some code which would send HTTP GET/POST requests to a target server. The problem arises, when the application attempts to establish a connection to a secure server (https). I used HttpsURLConnection for that purpose, as follows:

url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";
HttpsURLConnection con;

con = (HttpsURLConnection)url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

while ((input = br.readLine()) != null){
    htmlResponse += input;
}
br.close();

however, it showed the following error:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Therefore, I changed the above code like this:

url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";

SSLUtilities.trustAllHostnames();
SSLUtilities.trustAllHttpsCertificates();
HttpsURLConnection con;
// code below has not been changed

which used SSLUtilities.java. However, I noticed that doing so had no effect whatsoever, since I still received the exact same error, again:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Similarly, I also tried using a different approach, which involved using SSLCertificateValidation.java by using this line before starting the HttpsURLConnection:

SSLCertificateValidation.disable();

and even using that returned the exact same error as explained previously. I would like to know exactly why this approach is not working and how could I possibly get circumvent this error?

Please note the following:

  1. Goes without saying that I have searched extensively on this issue and have already spent a considerable amount of time, trying different suggestions and code examples, but to no avail. I know this error has been coming up a lot in questions, but I failed to find a specific answer that already existed relating to my own.

  2. I am aware of and understand the security issues that arise as a result of disabling certificate validation. However, since this application would connect to 100 to 200 different servers (as and when required), managing the certificate on a per-server basis is not feasible. Therefore, unless someone can state a method of (a) retrieving, (b) storing, and (c) using the correct certificate on a per-server basis (at runtime), all of which must be done programmatically without any manual work, suggesting the "clean" way to do it is not a solution to this scenario.

Thanks.

Divulged
  • 23
  • 6
  • 1
    I tried to investigate the certificate of the server which I'm trying to connect to, in the examples above (https://www.sendspace.com/), and I thus found this: https://www.ssllabs.com/ssltest/analyze.html?d=sendspace.com which clearly states an issue in all Java versions with the handshake. But that still doesn't explain why the validation disable attempts aren't working. – Divulged Aug 20 '15 at 15:39
  • The code you cite appears to be at least 11 years old and of dubious quality. The `com.sun.ssl.*` classes haven't been used with SSL since 1.4. – user207421 Aug 20 '15 at 15:49
  • @EJP: I believe you are referring to the code within SSLUtilities.java, what about the second method I used? Should it not work? And moreover, could you direct me to a method which would work for my purpose? Thanks. – Divulged Aug 20 '15 at 15:57

1 Answers1

3

A handshake failure is not a certificate validation error, so you cannot fix it by ignoring certificate errors (which is a bad idea anyway). The SSLLabs page more clearly states the real cause of the problem:

Java 8u31   Protocol or cipher suite mismatch   

If you look at the ciphers supported by the server (again in the SSLLabs report) you can see that all ciphers contain AES with a key size of 256. But in the documentation about supported key sizes it is stated that because of export restriction the maximum supported key size for AES is 128. This means your client offers only AES128 ciphers whereas the server only accepts AES256 ciphers, that is there are no shared ciphers.

To fix the issue you must do as described in the referenced documentation:

If stronger algorithms are needed (for example, AES with 256-bit keys), the JCE Unlimited Strength Jurisdiction Policy Files must be obtained and installed in the JDK/JRE.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Thanks. Even though I knew about the SSLLabs page beforehand, the key length difference didn't occur to me. However, I would like to add to the above answer, some more solutions for people who do not wish to go through the manual work of adding the JCE files to the JDK/JRE. For a complete description, please check this answer: http://stackoverflow.com/a/22492582/4905539 – Divulged Aug 21 '15 at 07:30
  • Thank you. I changed my platform from 1.7 to 1.8 and everything works now. – Jeff_Alieffson Dec 11 '17 at 06:26