web-dev-qa-db-fra.com

Android Activer TLSv1.2 dans OKHttp

j'utilise OKHttp pour mon projet. je veux activer TLSv1.2 pour mon appel de service. n'importe quel organisme peut-il me dire comment l'activer.

18

Pour autant que je sache, OKHttp n'inclut pas ses propres bibliothèques SSL/TLS, il utilise donc simplement le SSLSocket standard fourni par Android.

Les versions TLS prises en charge (et activées) dépendent de la version utilisée Android version. Sur certains téléphones, TLS 1.2 est pris en charge mais n'est pas activé par défaut. Dans de tels cas, vous pouvez l'activer en implémentant un wrapper personnalisé SSLSocketFactory qui utilise en interne le SSLSocketFactory par défaut et appelle setEnabledProtocols(new String{"TLS1.2"}) sur chaque Socket créé.

9
Robert

Voir OkHttp documentation HTTPS .

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));
9
Jesse Wilson

Vérifiez mon code!

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();
        }
    }
}
4
wei wang

Il s'avère que ma solution est très similaire à celle de Ken (sauf en Java). Je l'ai trouvé ici bien que j'ai dû faire quelques petits changements pour le faire fonctionner. Espérons que cela fonctionne ' hors de la boîte ' pour les autres.

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();
    }
2
aaronmarino

C'est fondamentalement la même que la réponse ci-dessus mais j'ai l'impression qu'un exemple de code serait utile pour toute autre personne qui atterrit ici et n'est pas à la hauteur sur la navigation dans le paysage SSL Java.

Ce qui a finalement fonctionné pour moi était basé sur le problème signalé ici: https://github.com/mattleibow/square-bindings/issues/1
de ce Gist https://Gist.github.com/mattleibow/c8abfa323db094b820cc

Notez que ces exemples de code sont en C #/Xamarin mais peuvent être traduits assez facilement en Java.

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;
    }
}

Et puis l'appeler comme:

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

Cela a fonctionné pour moi, testé sur l'API 19.

0
Ken Sykora