wake-up-neo.net

Android 4.4.2 SSL-Handshake abgebrochen

Der Code funktioniert auf meinem Emulator Genymotion Android 4.4.4, jedoch nicht auf dem von mir verwendeten Gerät (4.4.2).

Ich habe viele Problemumgehungen für "Alle Zertifikate vertrauen" ausprobiert, aber ohne Erfolg (ich glaube nicht, dass dies das Problem ist, da das Zertifikat AOK ist).

Ich glaube, ich habe die Chiffre identifiziert (mit einer Wireshark-Spur von meinem Desktop aus). TLS 0x00 0x1E Was scheint etwas selten zu sein?

Irgendeine Idee, wie man repariert?

Hier ist mein Code

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
CloseableHttpClient client = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();
String baseURL = "https://mysite.co.uk/api/";
HttpGetHC4 request = new HttpGetHC4(baseURL + "/authenticate?user=abcd&password=1234");
CloseableHttpResponse response = client.execute(request);

Und Irrtum;

 javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6abff398: Failure in SSL library, usually a protocol error
 error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x684dfce0:0x00000000)
     at com.Android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:449)
     at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.Java:340)
     at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.Java:281)
     at org.Apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.Java:124)
     at org.Apache.http.impl.conn.BasicHttpClientConnectionManager.connect(BasicHttpClientConnectionManager.Java:322)
     at org.Apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.Java:373)
     at org.Apache.http.impl.execchain.MainClientExec.execute(MainClientExec.Java:225)
     at org.Apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.Java:195)
     at org.Apache.http.impl.execchain.RetryExec.execute(RetryExec.Java:86)
     at org.Apache.http.impl.execchain.RedirectExec.execute(RedirectExec.Java:108)
     at org.Apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.Java:178)
     at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:82)
     at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:106)
     at com.example.lee.printticket.Main$OrderAsyncTask.onPostExecute(Main.Java:239)
     at com.example.lee.printticket.Main$OrderAsyncTask.onPostExecute(Main.Java:189)
     at Android.os.AsyncTask.finish(AsyncTask.Java:632)
     at Android.os.AsyncTask.access$600(AsyncTask.Java:177)
     at Android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.Java:645)
     at Android.os.Handler.dispatchMessage(Handler.Java:102)
     at Android.os.Looper.loop(Looper.Java:136)
     at Android.app.ActivityThread.main(ActivityThread.Java:5017)
     at Java.lang.reflect.Method.invokeNative(Native Method)
     at Java.lang.reflect.Method.invoke(Method.Java:515)
     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:785)
     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:601)
     at dalvik.system.NativeStart.main(Native Method)
 Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6abff398: Failure in SSL library, usually a protocol error
 error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x684dfce0:0x00000000)
     at com.Android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
     at com.Android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:406)
    ... 25 more

EDIT

Versuchen Sie es mit einer anderen Technik/Bibliothek.

        RequestQueue queue = Volley.newRequestQueue(this);
        String url ="https://mysite.co.uk/api/authenticate?user=abcd&password=1234";

        // Request a string response from the provided URL.
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        // Display the first 500 characters of the response string.
                        Log.d("response: ", response);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d("response: ", error.toString());
            }
        });
        // Add the request to the RequestQueue.
        queue.add(stringRequest);

Kehrt zurück;

D/response:: com.Android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6ad51be0: Failure in SSL library, usually a protocol error
D/response:: error:140740B5:SSL routines:SSL23_CLIENT_HELLO:no ciphers available (external/openssl/ssl/s23_clnt.c:486 0x684dfce0:0x00000000)

Oder mit dem NoSSLv3SocketFactory-Hack von Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochen: Fehler in der SSL-Bibliothek, in der Regel ein Protokollfehler ;

        HttpStack stack = new HurlStack(null, new NoSSLv3SocketFactory());
        RequestQueue queue = Volley.newRequestQueue(this, stack);

Kehrt zurück;

D/response:: com.Android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6ae51d30: Failure in SSL library, usually a protocol error
D/response:: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x684dfce0:0x00000000)
22
Lee Tickett

Android verwendet unterschiedliche Protokolle für den Netzwerkbetrieb.

Standardkonfiguration für verschiedene Android-Versionen.

Ich habe eine Lösung für OkHttpClient gefunden.

Protocol    Supported (API Levels)  Enabled by default (API Levels)

SSLv3       1–25                    1–22
TLSv1       1+                      1+
TLSv1.1     16+                     20+
TLSv1.2     16+                     20+

Wir müssen also das Protokoll für die Verbindung in Android VERSION> = 16 & VERSION <22 ändern.

Java-Datei erstellen Tls12SocketFactory.Java

/**
 * Enables TLS v1.2 when creating SSLSockets.
 * <p/>
 * For some reason, Android supports TLS v1.2 from API 16, but enables it by
 * default only from API 20.
 * @link https://developer.Android.com/reference/javax/net/ssl/SSLSocket.html
 * @see SSLSocketFactory
 */
public class Tls12SocketFactory extends SSLSocketFactory {
    private static final String[] TLS_V12_ONLY = {"TLSv1.2"};

    final SSLSocketFactory delegate;

    public Tls12SocketFactory(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;
    }
}

Fügen Sie diese Methode an einer beliebigen Stelle in Ihren Code ein.

public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) {
        if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
            try {
                SSLContext sc = SSLContext.getInstance("TLSv1.2");
                sc.init(null, null, null);
                client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));

                ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                        .tlsVersions(TlsVersion.TLS_1_2).build();

                List<ConnectionSpec> specs = new ArrayList<>();
                specs.add(cs);
                specs.add(ConnectionSpec.COMPATIBLE_TLS);
                specs.add(ConnectionSpec.CLEARTEXT);

                client.connectionSpecs(specs);
            } catch (Exception exc) {
                Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);
            }
        }

        return client;
    }

    public OkHttpClient getNewHttpClient() {
        OkHttpClient.Builder client = new OkHttpClient.Builder().followRedirects(true).followSslRedirects(true)
                .retryOnConnectionFailure(true).cache(null).connectTimeout(5, TimeUnit.SECONDS)
                .writeTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS);

        return enableTls12OnPreLollipop(client).build();
    }

Erstellen Sie die OkHttp-Instanz wie folgt:

private OkHttpClient getNewHttpClient() {
    OkHttpClient.Builder client = new OkHttpClient.Builder()
            .followRedirects(true)
            .followSslRedirects(true)
            .retryOnConnectionFailure(true)
            .cache(null)
            .connectTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS);

    return enableTls12OnPreLollipop(client).build();
}

Verwenden Sie ein Client-Objekt wie folgt:

OkHttpClient client = getNewHttpClient();
Request.Builder requestBuilder = new Request.Builder();
URL url = new URL("YOUR_URL_LINK");
Request request = requestBuilder.url(url).build();
Call call = client.newCall(request);
Response response = call.execute();

VIELEN DANK

2
user9453341

Versuche dies:

public class ClientSSLSocketFactory {

    public static SSLSocketFactory getSocketFactory(Context context) {
        try {
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            };
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[]{tm}, new SecureRandom());

            SSLSocketFactory ssf = SSLCertificateSocketFactory.getDefault(10000, new SSLSessionCache(context));
            return ssf;
        } catch (Exception ex) {
            Log.e("ssl", "Error during the getSocketFactory");
            ex.printStackTrace();
            return null;
        }
    }
}

Und beim Erstellen der Warteschlange:

sRequestQueue = Volley.newRequestQueue(context, new HurlStack(null, ClientSSLSocketFactory.getSocketFactory()));

Ich hoffe es hilft.

0
GuilhE

Ich glaube, das Problem ist SSL v3, das auf solchen Zeichenfolgen basiert, was darauf hindeutet, dass es versucht, SSL v3 zu verwenden: SSL23_GET_SERVER_HELLO: sslv3 

SSL v3 wird von der meisten modernen Software als unsicher angesehen und daher deaktiviert (selbst an Orten, an denen Sie sonst erwarten würden, dass es funktioniert, haben viele Unternehmen es einfach rausgerissen). Ich sehe auch aus der Stack-Ablaufverfolgung, dass der Code den Apache-HTTP-Client verwendet: Org.Apache.http.impl.client

Sie müssen also verhindern, dass der Apache-HTTP-Client SSL-v3 verwendet. Der Apache-HTTP-Client ist separat von den Standard-Java-SSL/TLS-Bibliotheken vorhanden. 

Es gibt eine weitere Stackoverflow-Frage, die keine Antworten erhielt: Wie kann ich SSLv3 in Apache HttpClient deaktivieren?

Dieser Link sieht vielversprechend aus: https://discretemkt.wordpress.com/2014/11/16/commons-httpclient-can-disable-sslv3/

Dort ist die Schlüssellinie 

Protocol.registerProtocol(scheme, customHttps);

Dieser Aufruf ermöglicht es Ihnen, die vorhandene SSL-Fabrik zu umgehen. Wenn Sie diesen Code zuerst ausführen, funktioniert er möglicherweise, sofern die Apache-HTTP-Client-Versionen kompatibel sind.

Beachten Sie auch, dass TLS 1.0 heutzutage auch als unsicher gilt. TLS 1.2 und 1.3 und der Standard jetzt.

0
Sean F