Android Enable TLSv1.2 in OKHttp

后端 未结 5 1771
旧时难觅i
旧时难觅i 2020-12-08 16:06

i am using OKHttp for my project. i want to enable TLSv1.2 for my service call. can any body tell me how to enable it.

相关标签:
5条回答
  • 2020-12-08 16:24

    As far as I know OKHttp does not include own SSL/TLS libraries, therefore it just uses the standard SSLSocket provided by Android.

    What TLS versions are supported (and enabled) depends on the used Android version. On some phone TLS 1.2 is supported but not enabled by default. In such cases you could enable it by implementing a custom wrapper SSLSocketFactory that uses internally the default SSLSocketFactory and calls setEnabledProtocols(new String{"TLS1.2"}) on every Socket that is created.

    0 讨论(0)
  • 2020-12-08 16:25

    Check My Code!!Working perfect!

    private void checkTls() {
        if (android.os.Build.VERSION.SDK_INT < 21) {
            try {
                ProviderInstaller.installIfNeededAsync(this, new ProviderInstaller.ProviderInstallListener() {
                    @Override
                    public void onProviderInstalled() {
                    }
    
                    @Override
                    public void onProviderInstallFailed(int i, Intent intent) {
                    }
                });
            } catch (Exception e) {
                finish();
                e.printStackTrace();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-08 16:28

    See OkHttp’s HTTPS documentation.

    ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) 
      .tlsVersions(TlsVersion.TLS_1_2)
      .cipherSuites( 
         CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
         CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
         CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
      .build();
    OkHttpClient client = ... 
    client.setConnectionSpecs(Collections.singletonList(spec));
    
    0 讨论(0)
  • 2020-12-08 16:36

    Turns out my solution is very similar to Ken's (except in Java). I found it here although had to make a couple of small changes to get it to work. Hopefully this works 'out of the box' for others.

    public class TLSSocketFactoryCompat extends SSLSocketFactory {
    
    private SSLSocketFactory internalSSLSocketFactory;
    
    public TLSSocketFactoryCompat() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        internalSSLSocketFactory = context.getSocketFactory();
    }
    
    public TLSSocketFactoryCompat(TrustManager[] tm) throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tm, new java.security.SecureRandom());
        internalSSLSocketFactory = context.getSocketFactory();
    }
    
    @Override
    public String[] getDefaultCipherSuites() {
        return internalSSLSocketFactory.getDefaultCipherSuites();
    }
    
    @Override
    public String[] getSupportedCipherSuites() {
        return internalSSLSocketFactory.getSupportedCipherSuites();
    }
    
    @Override
    public Socket createSocket() throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
    }
    
    @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));
    }
    
    private Socket enableTLSOnSocket(Socket socket) {
        if(socket != null && (socket instanceof SSLSocket)) {
            //Create list of supported protocols
            ArrayList<String> supportedProtocols = new ArrayList<>();
            for (String protocol : ((SSLSocket)socket).getEnabledProtocols()) {
    
                //Log.d("TLSSocketFactory", "Supported protocol:" + protocol);
                //Only add TLS protocols (don't want ot support older SSL versions)
                if (protocol.toUpperCase().contains("TLS")) {
                    supportedProtocols.add(protocol);
                }
            }
            //Force add TLSv1.1 and 1.2 if not already added
            if (!supportedProtocols.contains("TLSv1.1")) {
                supportedProtocols.add("TLSv1.1");
            }
            if (!supportedProtocols.contains("TLSv1.2")) {
                supportedProtocols.add("TLSv1.2");
            }
    
            String[] protocolArray = supportedProtocols.toArray(new String[supportedProtocols.size()]);
            /*for (int i = 0; i < protocolArray.length; i++) {
                Log.d("TLSSocketFactory", "protocolArray[" + i + "]" + protocolArray[i]);
            }*/
    
            //enable protocols in our list
            ((SSLSocket)socket).setEnabledProtocols(protocolArray);
        }
        return socket;
      }
    }
    

    Usage:

        OkHttpClient httpClient = new OkHttpClient();
        //Add Custom SSL Socket Factory which adds TLS 1.1 and 1.2 support for Android 4.1-4.4
        try {
            httpClient.setSslSocketFactory(new TLSSocketFactoryCompat());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    
    0 讨论(0)
  • 2020-12-08 16:40

    This is basically the same as the answer above but I feel like a code sample would be useful for anyone else who lands here and isn't up to speed on navigating the java ssl landscape.

    What ultimately ended up working for me was based on the issue reported here: https://github.com/mattleibow/square-bindings/issues/1
    from this gist https://gist.github.com/mattleibow/c8abfa323db094b820cc

    Note these code samples are in C# / Xamarin but can be translated to java fairly easily.

    internal class CompleteSSLSocketFactory : SSLSocketFactory
    {
        private readonly SSLSocketFactory innerFactory;
    
        public CompleteSSLSocketFactory (SSLSocketFactory innerFactory)
        {
            this.innerFactory = innerFactory;
        }
    
        public override string[] GetDefaultCipherSuites ()
        {
            return innerFactory.GetDefaultCipherSuites ();
        }
    
        public override string[] GetSupportedCipherSuites ()
        {
            return innerFactory.GetSupportedCipherSuites ();
        }
    
        public override Socket CreateSocket ()
        {
            return MakeSocketSafe (innerFactory.CreateSocket ());
        }
    
        public override Socket CreateSocket (Socket s, string host, int port, bool autoClose)
        {
            return MakeSocketSafe (innerFactory.CreateSocket (s, host, port, autoClose));
        }
    
        public override Socket CreateSocket (string host, int port)
        {
            return MakeSocketSafe (innerFactory.CreateSocket (host, port));
        }
    
        public override Socket CreateSocket (string host, int port, InetAddress localHost, int localPort)
        {
            return MakeSocketSafe (innerFactory.CreateSocket (host, port, localHost, localPort));
        }
    
        public override Socket CreateSocket (InetAddress host, int port)
        {
            return MakeSocketSafe (innerFactory.CreateSocket (host, port));
        }
    
        public override Socket CreateSocket (InetAddress address, int port, InetAddress localAddress, int localPort)
        {
            return MakeSocketSafe (innerFactory.CreateSocket (address, port, localAddress, localPort));
        }
    
        private Socket MakeSocketSafe (Socket socket)
        {
            var sslSocket = socket as SSLSocket;
            if (sslSocket != null) {
                // enable all supported protocols for this socket
                sslSocket.SetEnabledProtocols (sslSocket.GetSupportedProtocols ());
                sslSocket.SetEnabledCipherSuites (sslSocket.GetSupportedCipherSuites ());
            }
            return socket;
        }
    }
    

    And then calling it like:

    // this.client is an OkHttpClient
    if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) {
        this.client.SetSslSocketFactory(new CompleteSSLSocketFactory(HttpsURLConnection.DefaultSSLSocketFactory));
    }
    

    This worked for me, tested on API 19.

    0 讨论(0)
提交回复
热议问题