Enable TLS 1.1/1.2 for Android 4.X in React Native

Viewed 2456

I'm in the process of making a React Native app that has a minSdkVersion of 16 (Android 4.1). It makes requests to HTTPS pages where the server has disabled TLS 1.0. From my understanding Android 4.X has TLS 1.1/1.2 capabilities, but they need to be invoked specifically. I found several people claiming to fix this, but those seem like pure Java solutions. For example:

Even with all that talk, what I can't wrap my head around and am wonder is this:

  • Is it possible to solve this in any way without forking React Native?

I see this commit which seems like a feasible solution, but it does invade into the React Native source code, and I'd prefer to not have possible conflicts there in the future. I also see that you can create a custom SSLSocketFactory, but then how do I make all the requests through React Native use that factory? I also hear that you might have to update the device SSL version in some cases, but that doesn't really help if I can't invoke TLS 1.1/1.2 for my requests.

2 Answers

After numerous attempts to solve it, there is only one way that worked for me. Essentially you need to add a Java security package from Google to enable TLSv1/ TLSv1.1/ TLSv1.2 on old Android versions (< 5.0). This will also add support for TLSv1.3 as well as increase the apk size, but I guess we'll have to live with it.

Add the package in app/build.gradle:

implementation 'org.conscrypt:conscrypt-android:2.1.0'

Update MainApplication.java to use the new security provider:

@Override
public void onCreate() {
super.onCreate();

Security.insertProviderAt(new org.conscrypt.OpenSSLProvider(), 1);

//...
} 

As I understand this is the SSL issue. If I true you can try the following steps:

  1. Create a Java class SSLCertificateHandler to enable SSL with the function below:

    public static void trustSSL() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                X509Certificate[] myTrustedAnchors = new X509Certificate[0];
                return myTrustedAnchors;
            }
    
            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
    
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception e) {
    }}
    
  2. Call it from MainApplication class:

    public void onCreate() {
    super.onCreate();
    SSLCertificateHandler.trustSSL();}
    
Related