wake-up-neo.com

So aktivieren Sie die TLS 1.2-Unterstützung in einer Android-Anwendung (unter Android 4.1 JB)

Gemäß den Dokumenten in Android für SSLSocket und SSLContext werden die Protokolle TLS v1.1 und v1.2 in API-Level 16+ unterstützt, sind jedoch standardmäßig nicht aktiviert. http://developer.Android.com/reference/javax/net/ssl/SSLSocket.htmlhttp://developer.Android.com/reference/javax/net/ssl/SSLContext.html

Wie aktiviere ich es auf einem Gerät mit Android 4.1 oder höher (aber unter 5.0)?

Ich habe versucht, eine benutzerdefinierte SSLSocketFactory zu erstellen, die alle unterstützten Protokolle aktiviert, wenn Socket erstellt werden, und später meine benutzerdefinierte Implementierung verwendet als:

HttpsURLConnection.setDefaultSSLSocketFactory (neues MySSLSocketFactory ());

public class MySSLSocketFactory extends SSLSocketFactory {

        private SSLContext sc;
        private SSLSocketFactory ssf;  

        public MySSLSocketFactory() {
            try {
                sc = SSLContext.getInstance("TLS");
                sc.init(null, null, null);
                ssf = sc.getSocketFactory();

            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }  
        }

        @Override
        public Socket createSocket(Socket s, String Host, int port, boolean autoClose)
                throws IOException {
            SSLSocket ss = (SSLSocket) ssf.createSocket(s, Host, port, autoClose);
            ss.setEnabledProtocols(ss.getSupportedProtocols());
            ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
            return ss;
        }

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

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

        @Override
        public Socket createSocket(String Host, int port) throws IOException, UnknownHostException {
            SSLSocket ss = (SSLSocket) ssf.createSocket(Host, port);
            ss.setEnabledProtocols(ss.getSupportedProtocols());
            ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
            return ss;
        }

        @Override
        public Socket createSocket(InetAddress Host, int port) throws IOException {
            SSLSocket ss = (SSLSocket) ssf.createSocket(Host, port);
            ss.setEnabledProtocols(ss.getSupportedProtocols());
            ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
            return ss;
        }

        @Override
        public Socket createSocket(String Host, int port, InetAddress localHost, int localPort)
                throws IOException, UnknownHostException {
            SSLSocket ss = (SSLSocket) ssf.createSocket(Host, port, localHost, localPort);
            ss.setEnabledProtocols(ss.getSupportedProtocols());
            ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
            return ss;
        }

        @Override
        public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
                int localPort) throws IOException {
            SSLSocket ss = (SSLSocket) ssf.createSocket(address, port, localAddress, localPort);
            ss.setEnabledProtocols(ss.getSupportedProtocols());
            ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
            return ss;
        }
    }

Bei dem Versuch, eine Verbindung mit einem Server herzustellen, auf dem Nur TLS 1.2 aktiviert ist, tritt dennoch eine Ausnahme auf.

Hier ist die Ausnahme, die ich bekomme:

03-09 09: 21: 38.427: W/System.err (2496): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochen: ssl = 0xb7fa0620: Fehler in der SSL-Bibliothek, normalerweise ein Protokoll Error

03-09 09: 21: 38.427: W/System.err (2496): Fehler: 14077410: SSL-Routinen: SSL23_GET_SERVER_HELLO: SSLV3-Warnungs-Handshake-Fehler (external/openssl/ssl/s23_clnt.c: 741 0xa90e6990: 0x00000000)

56

Zwei Möglichkeiten zum Aktivieren von TLSv1.1 und TLSv1.2: 

  1. verwenden Sie diese Richtlinie: http://blog.dev-area.net/2015/08/13/Android-4-1-enable-tls-1-1-and-tls-1-2/
  2. verwenden Sie diese Klasse https://github.com/erickok/transdroid/blob/master/app/src/main/Java/org/transdroid/daemon/util/TlsSniSocketFactory.Java
    schemeRegistry.register(new Scheme("https", new TlsSniSocketFactory(), port));
18
tran minh linh

Ich habe dieses Problem mit den Angaben in Artikel http://blog.dev-area.net/2015/08/13/Android-4-1-enable-tls-1-1-and-tls-1 gelöst -2/ mit kleinen Änderungen.

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
SSLSocketFactory noSSLv3Factory = null;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KitKat) {
    noSSLv3Factory = new TLSSocketFactory(sslContext.getSocketFactory());
} else {
    noSSLv3Factory = sslContext.getSocketFactory();
}
connection.setSSLSocketFactory(noSSLv3Factory);

Dies ist der Code der benutzerdefinierten TLSSocketFactory:

public static class TLSSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory internalSSLSocketFactory;

    public TLSSocketFactory(SSLSocketFactory delegate) throws KeyManagementException, NoSuchAlgorithmException {
        internalSSLSocketFactory = delegate;
    }

    @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[]{TLS_v1_1, TLS_v1_2});
        }
        return socket;
    }

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

Edit: Danke an ademar111190 für die Kotlin-Implementierung ( link )

class TLSSocketFactory constructor(
        private val internalSSLSocketFactory: SSLSocketFactory
) : SSLSocketFactory() {

    private val protocols = arrayOf("TLSv1.2", "TLSv1.1")

    override fun getDefaultCipherSuites(): Array<String> = internalSSLSocketFactory.defaultCipherSuites

    override fun getSupportedCipherSuites(): Array<String> = internalSSLSocketFactory.supportedCipherSuites

    override fun createSocket(s: Socket, Host: String, port: Int, autoClose: Boolean) =
            enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, Host, port, autoClose))

    override fun createSocket(Host: String, port: Int) =
            enableTLSOnSocket(internalSSLSocketFactory.createSocket(Host, port))

    override fun createSocket(Host: String, port: Int, localHost: InetAddress, localPort: Int) =
            enableTLSOnSocket(internalSSLSocketFactory.createSocket(Host, port, localHost, localPort))

    override fun createSocket(Host: InetAddress, port: Int) =
            enableTLSOnSocket(internalSSLSocketFactory.createSocket(Host, port))

    override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int) =
            enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort))

    private fun enableTLSOnSocket(socket: Socket?) = socket?.apply {
        if (this is SSLSocket && isTLSServerEnabled(this)) {
            enabledProtocols = protocols
        }
    }

    private fun isTLSServerEnabled(sslSocket: SSLSocket) = sslSocket.supportedProtocols.any { it in protocols }

}
11
carlol

Ich habe einige Ergänzungen zu den oben genannten Antworten. Es handelt sich um einen Hack, den Jesse Wilson von okhttp, square hier erwähnt hat. Entsprechend diesem Hack musste ich meine SSLSocketFactory-Variable in umbenennen

private SSLSocketFactory delegate;

Dies ist meine TLSSocketFactory Klasse

public class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory delegate;

public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, null, null);
    delegate = context.getSocketFactory();
}

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

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

@Override
public Socket createSocket() throws IOException {
    return enableTLSOnSocket(delegate.createSocket());
}

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

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

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

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

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

private Socket enableTLSOnSocket(Socket socket) {
    if(socket != null && (socket instanceof SSLSocket)) {
        ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
    }
    return socket;
}
}

und so habe ich es mit okhttp und retrofit benutzt

 OkHttpClient client=new OkHttpClient();
    try {
        client = new OkHttpClient.Builder()
                .sslSocketFactory(new TLSSocketFactory())
                .build();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
5
Navneet Krishna

Du solltest benutzen

 SSLContext.getInstance("TLSv1.2"); 

für bestimmte Protokollversion.

Die zweite Ausnahme trat auf, weil default socketFactory das Fallback-SSLv3-Protokoll für Fehler verwendet hat.

Sie können NoSSLFactory aus der Hauptantwort hier zur Unterdrückung verwenden Wie kann ich SSLv3 in Android für HttpsUrlConnection deaktivieren?

Außerdem sollten Sie SSLContext mit allen Ihren Zertifikaten (Client und vertrauenswürdig, falls Sie sie benötigen) initiieren.

Aber das alles ist ohne Verwendung nutzlos 

ProviderInstaller.installIfNeeded(getContext())

Hier finden Sie weitere Informationen zum richtigen Einsatzszenario https://developer.Android.com/training/articles/security-gms-provider.html

Ich hoffe es hilft.

4

Wie das OP bereits sagte, werden die Protokolle TLS v1.1 und v1.2 in API-Level 16+ unterstützt, sind jedoch nicht standardmäßig aktiviert, sondern müssen nur aktiviert werden.

In diesem Beispiel wird HttpsUrlConnection und nicht HttpUrlConnection verwendet. Folgen Sie https://blog.dev-area.net/2015/08/13/Android-4-1-enable-tls-1-1-and-tls-1-2/ , wir können eine erstellen Fabrik

class MyFactory extends SSLSocketFactory {

    private javax.net.ssl.SSLSocketFactory internalSSLSocketFactory;

    public MyFactory() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        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)) {
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
        }
        return socket;
    }
}

Unabhängig davon, welche Netzwerkbibliothek Sie verwenden, stellen Sie sicher, dass ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); aufgerufen wird, damit der Socket TLS-Protokolle aktiviert hat.

Jetzt können Sie das in HttpsUrlConnection verwenden

class MyHttpRequestTask extends AsyncTask<String,Integer,String> {

    @Override
    protected String doInBackground(String... params) {
        String my_url = params[0];
        try {
            URL url = new URL(my_url);
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) url.openConnection();
            httpURLConnection.setSSLSocketFactory(new MyFactory());
            // setting the  Request Method Type
            httpURLConnection.setRequestMethod("GET");
            // adding the headers for request
            httpURLConnection.setRequestProperty("Content-Type", "application/json");


            String result = readStream(httpURLConnection.getInputStream());
            Log.e("My Networking", "We have data" + result.toString());


        }catch (Exception e){
            e.printStackTrace();
            Log.e("My Networking", "Oh no, error occurred " + e.toString());
        }

        return null;
    }

    private static String readStream(InputStream is) throws IOException {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("US-ASCII")));
        StringBuilder total = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            total.append(line);
        }
        if (reader != null) {
            reader.close();
        }
        return total.toString();
    }
}

Zum Beispiel

new MyHttpRequestTask().execute(myUrl);

Denken Sie auch daran, minSdkVersion in build.gradle auf 16 zu setzen

minSdkVersion 16
0
onmyway133

play-services-safetynet Bibliothek in Android build.gradle hinzufügen:

implementation 'com.google.Android.gms:play-services-safetynet:+'

und füge diesen Code zu deinem MainApplication.Java hinzu:

@Override
  public void onCreate() {
    super.onCreate();
    upgradeSecurityProvider();
    SoLoader.init(this, /* native exopackage */ false);
  }

  private void upgradeSecurityProvider() {
    ProviderInstaller.installIfNeededAsync(this, new ProviderInstallListener() {
      @Override
      public void onProviderInstalled() {

      }

      @Override
      public void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
//        GooglePlayServicesUtil.showErrorNotification(errorCode, MainApplication.this);
        GoogleApiAvailability.getInstance().showErrorNotification(MainApplication.this, errorCode);
      }
    });
  }
0
sajad abbasi

@ Inherently Curious - Vielen Dank für den Beitrag. Sie sind fast da - Sie müssen der Methode SSLContext.init () zwei weitere Parameter hinzufügen.

TrustManager[] trustManagers = new TrustManager[] { new TrustManagerManipulator() };
sc.init(null, trustManagers, new SecureRandom());

es wird anfangen zu arbeiten. Nochmals vielen Dank für das Posten. Ich habe dieses/mein Problem mit Ihrem Code gelöst.

0