Upgrade to TLSV1.0 or 1.1 to TLSV1.2 in android using httpclient

All we need is a simple explanation of the problem, which is provided below.

My application existing running tlsv1.0 or 1.1 and want to update tls version 1.2, but still showing old version tls1.0 or tls1.1 not showing 1.2. Sample code:

public class TLSSocketFactoryNew extends SSLSocketFactory {

    private SSLSocketFactory internalSSLSocketFactory;

    public TLSSocketFactoryNew() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        TrustManager[] managers = new TrustManager[] { new TrustManagerManipulator() };
        context.init(null, managers, new SecureRandom());
        internalSSLSocketFactory = context.getSocketFactory();

    }

    @Override
    public String[] getDefaultCipherSuites() {
        return internalSSLSocketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return internalSSLSocketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
    }

    /*
     * Utility methods
     */

    private static Socket enableTLSOnSocket(Socket socket) {
        if (socket != null && (socket instanceof SSLSocket)
                && isTLSServerEnabled((SSLSocket) socket)) { // skip the fix if server doesn't provide there TLS version
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
        }
        return socket;
    }

    private static boolean isTLSServerEnabled(SSLSocket sslSocket) {
        System.out.println("isTLSServerEnabled :: " + sslSocket.getSupportedProtocols().toString());
        for (String protocol : sslSocket.getSupportedProtocols()) {
            if (protocol.equals("TLSv1.1") || protocol.equals("TLSv1.2")) {
                return true;
            }
        }
        return false;
    }
}

My concern now is, I just want to make support my app only tlsv1.2 version, all the old version should be avoided.

How I made the call TLSSocketFactoryNew in my utility class, using only httpclient– don’t need solution about okhttp, httpurlconnection.

Util.java

HttpClient mHttpClient= returnHttpClient(httpParams);

and getting httpclient

private HttpClient returnHttpClient(HttpParams httpParams) {
    SchemeRegistry registry = new SchemeRegistry();
    try {
      registry.register(new Scheme("https", (SocketFactory) new TLSSocketFactoryNew(), 443));
    } catch (KeyManagementException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    HttpClient client = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, registry),httpParams);
    return  client;
  }

I added this snip on inside oncreate on Activity,

try {
            ProviderInstaller.installIfNeeded(getBaseContext());
        } catch (GooglePlayServicesRepairableException e) {
            e.printStackTrace();
        } catch (GooglePlayServicesNotAvailableException e) {
            e.printStackTrace();
        }

and dependencies:

compile 'com.google.android.gms:play-services-base:11.0.1'
compile files('libs/commons-codec-1.9.jar')
compile files('libs/commons-logging-1.1.1.jar')
compile files('libs/core-1.51.0.0.jar')
//  compile files('libs/httpclient-4.0.1.jar')
compile files('libs/httpcore-4.0.1.jar')
compile files('libs/jackson-core-2.7.2.jar')
compile files('libs/jsonic-1.3.0.jar')

I raise point here, where I am wrong to upgrade my tls version up to v1.2, am I missing something in my code?

Thanks in advance.

Let’s Solve it:

This is a common error many developers questioned us about it. So we write the explanation above. You just have to apply the suggested solution to your code and it will do for you. If you still getting this error after applying this code then comment below we will get back to you with the new method.

Solution 1

I this will gonna help for you, Exactly same issue, I solved by below snips:

Just Get the HttpClient:

private HttpClient getHttpClient(HttpParams httpParams) {
    SSLContext sslContext = null;
 try {
        sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, null);
        SSLSocketFactory delegate = null;
        delegate = new TLSSocketFactory(sslContext.getSocketFactory());
        HttpsURLConnection.setDefaultSSLSocketFactory(delegate);
        SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
        HttpClient httpclient = new DefaultHttpClient(httpParams);
        httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", socketFactory, 443));
       return httpclient;
 } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
 } catch (Exception e) {
        throw new RuntimeException(e);
 }
}

and TLSSocketFactory.java file should be

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class TLSSocketFactory extends SSLSocketFactory {
    private static final String[] TLS_V12_ONLY = {"TLSv1.2"};

    final SSLSocketFactory delegate;

    public TLSSocketFactory(SSLSocketFactory base) {
        this.delegate = base;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patch(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return patch(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket patch(Socket s) {
        if (s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY);
        }
        return s;
    }
}

if you want more learn please go following links:

https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/

https://medium.com/tech-quizlet/working-with-tls-1-2-on-android-4-4-and-lower-f4f5205629a

Solution 2

First make sure that whatever machine you are running this on has TLS 1.2 enabled.

Set the SSLContext:

SSLContext sslContext = SSLContextBuilder.create().useProtocol("TLSv1.2").build();

Then build your HttpClient with the HttpClientBuilder:

HttpClientBuilder builder = HttpClientBuilder.create();
builder.setSSLContext(sslContext);

Note: You are free to use these solutions for your personal use. We recommend you apply the first solution to your code because it was tested in our system before posting it on this page.

We are always trying to help the developer community, So we made their work easy. Basically, we collected these data from stackoverflow.com, As it is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0.

Leave a Comment