HTTPS request Received fatal alert: handshake_failure exception - reason different

Posted by robotman321 on Thu, 05 Sep 2019 05:36:19 +0200

Today I encountered a Received fatal alert: handshake_failure problem in my project. The direct translation just failed. To be honest, this is the first time I have encountered this problem.In forums, in the sea of technical blogs, I still haven't solved my problem.It was unexpected that a final omission found the cause.

First of all, I would like to tell you some experiences and solutions on the Internet, which is a summary.

We can both send requests with curl and postman, and the handshake succeeds. Code alone cannot request success.handshake_failure is by no means a cause.

Reason 1: Protocol versions of Https are inconsistent.The protocols are TLSv1.2,TLSv1.1,SSLv3

How do I determine this?

1: If you are running locally, you can do this by writing a communications client (only for testing handshakes)

The code was temporarily quoted by me and I couldn't get it off the server.

import java.io.DataInputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.net.ConnectException;  
import java.net.URL;  
import java.security.cert.CertificateException;  
import java.security.cert.X509Certificate;  
  
import javax.net.ssl.HostnameVerifier;  
import javax.net.ssl.HttpsURLConnection;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.SSLSession;  
import javax.net.ssl.TrustManager;  
import javax.net.ssl.X509TrustManager;    
  
public class HttpsTest {  
    private static class TrustAnyTrustManager implements X509TrustManager {  
    	@Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
        }  
    	@Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
        }  
    	@Override
        public X509Certificate[] getAcceptedIssuers() {  
            return null;  
        }  
    }  
    private static class TrustAnyHostnameVerifier implements HostnameVerifier {  
        public boolean verify(String hostname, SSLSession session) {  
            return true;  
        }  
    }  
    public static String sendHttps(String url) throws Exception {  
        InputStream in = null;  
        OutputStream out = null;  
        String returnValue = "";  
        try {  
            //SSLContext sc = SSLContext.getInstance("SSL");  
//            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");  
//            SSLContext sc = SSLContext.getInstance("TLS", "SunJSSE");
            SSLContext sc = SSLContext.getInstance("TLS");  
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());  
            URL console = new URL(url);  
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();  
            conn.setSSLSocketFactory(sc.getSocketFactory());  
//            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());  
            conn.setRequestMethod("POST");
            conn.connect();  
            InputStream is = conn.getInputStream();  
            DataInputStream indata = new DataInputStream(is);  
            returnValue = indata.readLine();              
            conn.disconnect();  
        } catch (ConnectException e) {  
            e.printStackTrace();
            throw e;  
        } catch (IOException e) {  
        	e.printStackTrace();
            throw e;  
        } finally {  
            try {  
                in.close();  
            } catch (Exception e) {  }  
            try {  
                out.close();  
            } catch (Exception e) { }  
        }  
        return returnValue;  
    }  
    public static void main(String[] args) throws Exception {  
        System.out.println(sendHttps("https://finance-23055.beta.qunar.com"));  
    }  
} 
## Code reload https://blog.csdn.net/dzy_001/article/details/81012959

Then set it in the run parameters

-Djavax.net.debug=all 

Then run, there will be the following, a lot of content, you can find these.

main, WRITE: TLSv1.2 Handshake, length = 191  ## This is the version sent by the client
[Raw write]: length = 196

main, READ: TLSv1.2 Alert, length = 2 ## This is the version returned by the server
main, RECV TLSv1.2 ALERT:  fatal, handshake_failure

Unfortunately, this does not solve my problem because both client and server sides are TLSv1.2.If you find that the two versions are different, you are in this situation. How to solve this problem, please read other articles. I will not go into details and give two recommendations.

http://www.voidcn.com/article/p-xjnaqnwd-bqu.html

https://blog.csdn.net/u014644574/article/details/83381303

2: The server does not support this protocol

SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
//Then use

openssl s_client -connect finance-23055.beta.qunar.com:443 -state -debug -tls1 -msg

//The message reply you see is like this:

read from 0xb644fc0 [0xb689760] (5 bytes => 5 (0x5)) 
0000 - 15 03 01 00 02 ..... 
read from 0xb644fc0 [0xb689765] (2 bytes => 2 (0x2)) 
0000 - 02 28
//Where 0x15 represents alert and 0x28 represents handshake failure

This makes it difficult to discover the server's support protocol, slow, guessed, and possibly unsure

https://www.ssllabs.com/ssltest/

Enter this address and enter the server address you want to test.Then a report will come out, very detailed.

The agreement makes it clear whether it is supported or not.There are more details below. Try it yourself.

3:SSL algorithm not supported

curl -d "" -k https://IP:port/tests -v

Using the above commands, we can clearly see the execution process.

One of the lines looks like this

SSL connection using  ********  ## *Represents the algorithm used by curl

This algorithm is ours.Let's see if our program supports this algorithm?

ctx.getSupportedSSLParameters().getCipherSuites()
ctx.getSocketFactory().getDefaultCipherSuites()
ctx.getSocketFactory().getSupportedCipherSuites()

## ctx is an SSLContext object

Print it out to see if curl's algorithm is supported in our java.

See: https://blog.csdn.net/qq_36783371/article/details/80665901

4: That's me, the saddest one.Look at my code above, if you remove this section, you won't fail to shake hands.This verification is also within the handshake process.

private static class TrustAnyHostnameVerifier implements HostnameVerifier {  
        public boolean verify(String hostname, SSLSession session) {  
            return true;  
        }  
    } 

Okay, that's all I've summarized.

 

 

Topics: SSL Java curl Session