Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochen: Fehler in der SSL-Bibliothek, normalerweise ein Protokollerrors

Ich versuche, den folgenden Code in Android auszuführen

URLConnection l_connection = null; // Create connection uzip=new UnZipData(mContext); l_url = new URL(serverurl); if ("https".equals(l_url.getProtocol())) { System.out.println("<<<<<<<<<<<<>>>>>>>>>>>"); sslcontext = SSLContext.getInstance("TLS"); System.out.println("<<<<<<<<<<<<>>>>>>>>>>>"); sslcontext.init(null, new TrustManager[] { new CustomTrustManager()}, new java.security.SecureRandom()); HttpsURLConnection .setDefaultHostnameVerifier(new CustomHostnameVerifier()); HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext .getSocketFactory()); l_connection = (HttpsURLConnection) l_url.openConnection(); ((HttpsURLConnection) l_connection).setRequestMethod("POST"); } else { l_connection = (HttpURLConnection) l_url.openConnection(); ((HttpURLConnection) l_connection).setRequestMethod("POST"); } /*System.setProperty("http.agent", "Android_Phone");*/ l_connection.setConnectTimeout(10000); l_connection.setRequestProperty("Content-Language", "en-US"); l_connection.setUseCaches(false); l_connection.setDoInput(true); l_connection.setDoOutput(true); System.out.println("<<<<<<<<<<<<>>>>>>>>>>>"); l_connection.connect(); 

Auf l_connection.connect() gibt es diese SSLhandshakeException. Manchmal funktioniert es, aber meistens gibt es die Ausnahme. Es geschieht nur auf Android 4.0 Emulator. Ich habe es auf Android 4.4 und 5.0 getestet, es funktioniert gut. Was könnte die Ursache dafür sein? Bitte helfen Sie

STAPELTRACK

  04-28 15:51:13.143: W/System.err(2915): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error 04-28 15:51:13.143: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000) 04-28 15:51:13.143: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460) 04-28 15:51:13.143: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257) 04-28 15:51:13.143: W/System.err(2915): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210) 04-28 15:51:13.143: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477) 04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441) 04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282) 04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232) 04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80) 04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164) 04-28 15:51:13.153: W/System.err(2915): at com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170) 04-28 15:51:13.153: W/System.err(2915): at com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221) 04-28 15:51:13.153: W/System.err(2915): at java.lang.Thread.run(Thread.java:856) 04-28 15:51:13.153: W/System.err(2915): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error 04-28 15:51:13.153: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000) 04-28 15:51:13.153: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 04-28 15:51:13.153: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410) 04-28 15:51:13.153: W/System.err(2915): ... 11 more 04-28 16:42:44.139: W/ResourceType(3140): No package identifier when getting value for resource number 0x00000000 

    Ich habe die Lösung dafür gefunden, indem ich die Datenpakete mit wireshark analysiert habe. Was ich fand, ist, dass Android während der Herstellung einer sicheren Verbindung von TLSv1 zurück zu SSLv3 fiel . Es ist ein Fehler in Android-Versionen <4.4, und es kann durch Entfernen des SSLv3-Protokolls aus der Liste der aktivierten Protokolle gelöst werden. Ich habe eine benutzerdefinierte socketFactory-Klasse namens NoSSLv3SocketFactory.java erstellt. Verwenden Sie dies, um eine Socketfactory zu erstellen.

     /*Copyright 2015 Bhavit Singh Sengar Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.*/ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; public class NoSSLv3SocketFactory extends SSLSocketFactory{ private final SSLSocketFactory delegate; public NoSSLv3SocketFactory() { this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); } public NoSSLv3SocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } private Socket makeSocketSafe(Socket socket) { if (socket instanceof SSLSocket) { socket = new NoSSLv3SSLSocket((SSLSocket) socket); } return socket; } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return makeSocketSafe(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort)); } private class NoSSLv3SSLSocket extends DelegateSSLSocket { private NoSSLv3SSLSocket(SSLSocket delegate) { super(delegate); } @Override public void setEnabledProtocols(String[] protocols) { if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { List enabledProtocols = new ArrayList(Arrays.asList(delegate.getEnabledProtocols())); if (enabledProtocols.size() > 1) { enabledProtocols.remove("SSLv3"); System.out.println("Removed SSLv3 from enabled protocols"); } else { System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); } protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]); } super.setEnabledProtocols(protocols); } } public class DelegateSSLSocket extends SSLSocket { protected final SSLSocket delegate; DelegateSSLSocket(SSLSocket delegate) { this.delegate = delegate; } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public String[] getEnabledCipherSuites() { return delegate.getEnabledCipherSuites(); } @Override public void setEnabledCipherSuites(String[] suites) { delegate.setEnabledCipherSuites(suites); } @Override public String[] getSupportedProtocols() { return delegate.getSupportedProtocols(); } @Override public String[] getEnabledProtocols() { return delegate.getEnabledProtocols(); } @Override public void setEnabledProtocols(String[] protocols) { delegate.setEnabledProtocols(protocols); } @Override public SSLSession getSession() { return delegate.getSession(); } @Override public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.addHandshakeCompletedListener(listener); } @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.removeHandshakeCompletedListener(listener); } @Override public void startHandshake() throws IOException { delegate.startHandshake(); } @Override public void setUseClientMode(boolean mode) { delegate.setUseClientMode(mode); } @Override public boolean getUseClientMode() { return delegate.getUseClientMode(); } @Override public void setNeedClientAuth(boolean need) { delegate.setNeedClientAuth(need); } @Override public void setWantClientAuth(boolean want) { delegate.setWantClientAuth(want); } @Override public boolean getNeedClientAuth() { return delegate.getNeedClientAuth(); } @Override public boolean getWantClientAuth() { return delegate.getWantClientAuth(); } @Override public void setEnableSessionCreation(boolean flag) { delegate.setEnableSessionCreation(flag); } @Override public boolean getEnableSessionCreation() { return delegate.getEnableSessionCreation(); } @Override public void bind(SocketAddress localAddr) throws IOException { delegate.bind(localAddr); } @Override public synchronized void close() throws IOException { delegate.close(); } @Override public void connect(SocketAddress remoteAddr) throws IOException { delegate.connect(remoteAddr); } @Override public void connect(SocketAddress remoteAddr, int timeout) throws IOException { delegate.connect(remoteAddr, timeout); } @Override public SocketChannel getChannel() { return delegate.getChannel(); } @Override public InetAddress getInetAddress() { return delegate.getInetAddress(); } @Override public InputStream getInputStream() throws IOException { return delegate.getInputStream(); } @Override public boolean getKeepAlive() throws SocketException { return delegate.getKeepAlive(); } @Override public InetAddress getLocalAddress() { return delegate.getLocalAddress(); } @Override public int getLocalPort() { return delegate.getLocalPort(); } @Override public SocketAddress getLocalSocketAddress() { return delegate.getLocalSocketAddress(); } @Override public boolean getOOBInline() throws SocketException { return delegate.getOOBInline(); } @Override public OutputStream getOutputStream() throws IOException { return delegate.getOutputStream(); } @Override public int getPort() { return delegate.getPort(); } @Override public synchronized int getReceiveBufferSize() throws SocketException { return delegate.getReceiveBufferSize(); } @Override public SocketAddress getRemoteSocketAddress() { return delegate.getRemoteSocketAddress(); } @Override public boolean getReuseAddress() throws SocketException { return delegate.getReuseAddress(); } @Override public synchronized int getSendBufferSize() throws SocketException { return delegate.getSendBufferSize(); } @Override public int getSoLinger() throws SocketException { return delegate.getSoLinger(); } @Override public synchronized int getSoTimeout() throws SocketException { return delegate.getSoTimeout(); } @Override public boolean getTcpNoDelay() throws SocketException { return delegate.getTcpNoDelay(); } @Override public int getTrafficClass() throws SocketException { return delegate.getTrafficClass(); } @Override public boolean isBound() { return delegate.isBound(); } @Override public boolean isClosed() { return delegate.isClosed(); } @Override public boolean isConnected() { return delegate.isConnected(); } @Override public boolean isInputShutdown() { return delegate.isInputShutdown(); } @Override public boolean isOutputShutdown() { return delegate.isOutputShutdown(); } @Override public void sendUrgentData(int value) throws IOException { delegate.sendUrgentData(value); } @Override public void setKeepAlive(boolean keepAlive) throws SocketException { delegate.setKeepAlive(keepAlive); } @Override public void setOOBInline(boolean oobinline) throws SocketException { delegate.setOOBInline(oobinline); } @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth); } @Override public synchronized void setReceiveBufferSize(int size) throws SocketException { delegate.setReceiveBufferSize(size); } @Override public void setReuseAddress(boolean reuse) throws SocketException { delegate.setReuseAddress(reuse); } @Override public synchronized void setSendBufferSize(int size) throws SocketException { delegate.setSendBufferSize(size); } @Override public void setSoLinger(boolean on, int timeout) throws SocketException { delegate.setSoLinger(on, timeout); } @Override public synchronized void setSoTimeout(int timeout) throws SocketException { delegate.setSoTimeout(timeout); } @Override public void setTcpNoDelay(boolean on) throws SocketException { delegate.setTcpNoDelay(on); } @Override public void setTrafficClass(int value) throws SocketException { delegate.setTrafficClass(value); } @Override public void shutdownInput() throws IOException { delegate.shutdownInput(); } @Override public void shutdownOutput() throws IOException { delegate.shutdownOutput(); } @Override public String toString() { return delegate.toString(); } @Override public boolean equals(Object o) { return delegate.equals(o); } } } 

    Verwenden Sie diese class beim Verbinden folgendermaßen:

     SSLContext sslcontext = SSLContext.getInstance("TLSv1"); sslcontext.init(null, null, null); SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory); l_connection = (HttpsURLConnection) l_url.openConnection(); l_connection.connect(); 

    UPDATE:

    Die korrekte Lösung wäre nun, einen neueren Sicherheitsanbieter mithilfe der Google Play-Dienste zu installieren:

      ProviderInstaller.installIfNeeded(getApplicationContext()); 

    Dadurch erhält Ihre App effektiv Zugriff auf eine neuere Version von OpenSSL und Java Security Provider, die Unterstützung für TLSv1.2 in SSLEngine bietet. Sobald der neue Provider installiert ist, können Sie wie gewohnt eine SSLEngine erstellen, die SSLv3, TLSv1, TLSv1.1 und TLSv1.2 unterstützt:

      SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); SSLEngine engine = sslContext.createSSLEngine(); 

    Oder Sie können die aktivierten Protokolle mithilfe von engine.setEnabledProtocols .

    Vergessen Sie nicht, die folgende Abhängigkeit hinzuzufügen ( neueste Version hier gefunden ):

     compile 'com.google.android.gms:play-services-auth:11.8.0' 

    Weitere Informationen finden Sie unter diesem Link .

    Szenario

    Ich habe SSLHandshake-Ausnahmen auf Geräten mit Android-Versionen vor Android 5.0 erhalten. In meinem Anwendungsfall wollte ich auch einen TrustManager erstellen, um meinem Client-Zertifikat zu vertrauen.

    Ich habe NoSSLv3SocketFactory und NoSSLv3Factory implementiert, um SSLv3 aus der Liste der unterstützten Protokolle meines Clients zu entfernen, aber ich konnte keine dieser Lösungen zum Laufen bringen .

    Einige Dinge, die ich gelernt habe:

    • Auf älteren Geräten als Android 5.0 sind die Protokolle TLSv1.1 und TLSv1.2 standardmäßig nicht aktiviert.
    • Das SSLv3-Protokoll ist auf Geräten, die älter als Android 5.0 sind, nicht standardmäßig deaktiviert.
    • SSLv3 ist kein sicheres Protokoll und es ist daher wünschenswert, es aus der Liste der unterstützten Protokolle des Clients zu entfernen, bevor eine Verbindung hergestellt wird.

    Was für mich funktioniert hat

    Erlaube dem Android-Sicherheitsprovider, beim Start deiner App zu aktualisieren.

    Der Standardanbieter vor 5.0+ deaktiviert SSLv3 nicht. Sofern Sie Zugriff auf die Google Play-Dienste haben, ist es relativ einfach, den Android-Sicherheitsprovider von Ihrer App aus zu patchen.

     private void updateAndroidSecurityProvider(Activity callingActivity) { try { ProviderInstaller.installIfNeeded(this); } catch (GooglePlayServicesRepairableException e) { // Thrown when Google Play Services is not installed, up-to-date, or enabled // Show dialog to allow users to install, update, or otherwise enable Google Play services. GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0); } catch (GooglePlayServicesNotAvailableException e) { Log.e("SecurityException", "Google Play Services not available."); } } 

    Wenn Sie nun Ihren OkHttpClient oder HttpURLConnection TLSv1.1 erstellen, sollte TLSv1.2 als Protokolle verfügbar sein und SSLv3 sollte entfernt werden. Wenn der Client / die Verbindung (oder genauer gesagt, der SSLContext) vor dem Aufruf von ProviderInstaller.installIfNeeded(...) initialisiert wurde, muss er neu erstellt werden.

    Vergessen Sie nicht, die folgende Abhängigkeit hinzuzufügen ( neueste Version hier gefunden ):

     compile 'com.google.android.gms:play-services-auth:11.8.0' 

    Quellen:

    • Patchen des Sicherheitsproviders mit ProviderInstaller Provider
    • Machen Sie SSLEngine verwenden TLSv1.2 auf Android (4.4.2)

    Beiseite

    Ich musste nicht explizit festlegen, welche Verschlüsselungsalgorithmen mein Client verwenden sollte, aber ich fand einen SO-Post, der diejenigen vorschlägt, die zum Zeitpunkt des Schreibens als am sichersten angesehen wurden: Welche Cipher-Suites für den SSL-Socket aktivieren?

    Das hat es für mich getriggers:

    Die Android-Dokumentation für SSLSocket besagt, dass TLS 1.1 und TLS 1.2 in Android ab API-Level 16+ (Android 4.1, Jelly Bean) unterstützt werden. Aber es ist standardmäßig deaktiviert, aber ab API-Level 20+ (Android 4.4 für Watch, Kitkat Watch und Android 5.0 für Telefon, Lollipop) sind sie aktiviert. Aber es ist sehr schwierig, eine Dokumentation darüber zu finden, wie man es für Telefone mit 4.1 aktiviert. Um TLS 1.1 und 1.2 zu aktivieren, müssen Sie eine benutzerdefinierte SSLSocketFactory erstellen, die alle Aufrufe an eine SSLSocketFactory-Standardimplementierung annimmt. Darüber hinaus müssen wir alle createSocket-Methoden und callsetEnabledProtocols für die zurückgegebene SSLSocket überschreiben, um TLS 1.1 und TLS 1.2 zu aktivieren. Für eine Beispielimplementierung folgen Sie einfach dem unten stehenden Link.

    Android 4.1. Aktivieren Sie tls1.1 und tls 1.2

    Außerdem sollten Sie wissen, dass Sie TLS v1.2 für Android 4.0-Geräte erzwingen können, für die es standardmäßig nicht aktiviert ist:

    Dies sollte in der ersten Zeile Ihrer Anwendung sein:

     try { ProviderInstaller.installIfNeeded(getApplicationContext()); SSLContext sslContext; sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); sslContext.createSSLEngine(); } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } 

    Es war nur reproduzierbar, wenn ich Proxy auf Genymotion (<4.4) verwende.

    Überprüfen Sie Ihre Proxy-Einstellungen unter Einstellungen-> Drahtlos & Netzwerke-> WiFi -> (Lange Pressed WiredSSID) -> Netzwerk ändern

    Wählen Sie erweiterte Optionen anzeigen aus: Setzen Sie die Proxy-Einstellungen auf NONE.

    Vorher habe ich dieses Problem auch mit einer benutzerdefinierten SSLFactory-Implementierung getriggers, aber gemäß dieser OkHttp-Dokumentation ist die Lösung viel einfacher.

    Meine endgültige Lösung mit benötigten Verschlüsselungen für 4.2+ Geräte sieht folgendermaßen aus:

     public UsersApi provideUsersApi() { private ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) .supportsTlsExtensions(true) .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0) .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, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA) .build(); OkHttpClient client = new OkHttpClient.Builder() .connectionSpecs(Collections.singletonList(spec)) .build(); return new Retrofit.Builder() .baseUrl(USERS_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build() .create(UsersApi.class); } 

    Beachten Sie, dass die Anzahl der unterstützten Protokolle davon abhängt, wie sie auf Ihrem Server konfiguriert sind.

    Ich habe das Problem dadurch getriggers: NoSSLv3SocketFactory.java

     import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; public class NoSSLv3SocketFactory extends SSLSocketFactory { private final SSLSocketFactory delegate; public NoSSLv3SocketFactory() { this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); } public NoSSLv3SocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } private Socket makeSocketSafe(Socket socket) { if (socket instanceof SSLSocket) { socket = new NoSSLv3SSLSocket((SSLSocket) socket); } return socket; } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return makeSocketSafe(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort)); } private class NoSSLv3SSLSocket extends DelegateSSLSocket { private NoSSLv3SSLSocket(SSLSocket delegate) { super(delegate); } @Override public void setEnabledProtocols(String[] protocols) { if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { List enabledProtocols = new ArrayList( Arrays.asList(delegate.getEnabledProtocols())); if (enabledProtocols.size() > 1) { enabledProtocols.remove("SSLv3"); System.out.println("Removed SSLv3 from enabled protocols"); } else { System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); } protocols = enabledProtocols .toArray(new String[enabledProtocols.size()]); } // super.setEnabledProtocols(protocols); super.setEnabledProtocols(new String[]{"TLSv1.2"}); } } public class DelegateSSLSocket extends SSLSocket { protected final SSLSocket delegate; DelegateSSLSocket(SSLSocket delegate) { this.delegate = delegate; } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public String[] getEnabledCipherSuites() { return delegate.getEnabledCipherSuites(); } @Override public void setEnabledCipherSuites(String[] suites) { delegate.setEnabledCipherSuites(suites); } @Override public String[] getSupportedProtocols() { return delegate.getSupportedProtocols(); } @Override public String[] getEnabledProtocols() { return delegate.getEnabledProtocols(); } @Override public void setEnabledProtocols(String[] protocols) { delegate.setEnabledProtocols(protocols); } @Override public SSLSession getSession() { return delegate.getSession(); } @Override public void addHandshakeCompletedListener( HandshakeCompletedListener listener) { delegate.addHandshakeCompletedListener(listener); } @Override public void removeHandshakeCompletedListener( HandshakeCompletedListener listener) { delegate.removeHandshakeCompletedListener(listener); } @Override public void startHandshake() throws IOException { delegate.startHandshake(); } @Override public void setUseClientMode(boolean mode) { delegate.setUseClientMode(mode); } @Override public boolean getUseClientMode() { return delegate.getUseClientMode(); } @Override public void setNeedClientAuth(boolean need) { delegate.setNeedClientAuth(need); } @Override public void setWantClientAuth(boolean want) { delegate.setWantClientAuth(want); } @Override public boolean getNeedClientAuth() { return delegate.getNeedClientAuth(); } @Override public boolean getWantClientAuth() { return delegate.getWantClientAuth(); } @Override public void setEnableSessionCreation(boolean flag) { delegate.setEnableSessionCreation(flag); } @Override public boolean getEnableSessionCreation() { return delegate.getEnableSessionCreation(); } @Override public void bind(SocketAddress localAddr) throws IOException { delegate.bind(localAddr); } @Override public synchronized void close() throws IOException { delegate.close(); } @Override public void connect(SocketAddress remoteAddr) throws IOException { delegate.connect(remoteAddr); } @Override public void connect(SocketAddress remoteAddr, int timeout) throws IOException { delegate.connect(remoteAddr, timeout); } @Override public SocketChannel getChannel() { return delegate.getChannel(); } @Override public InetAddress getInetAddress() { return delegate.getInetAddress(); } @Override public InputStream getInputStream() throws IOException { return delegate.getInputStream(); } @Override public boolean getKeepAlive() throws SocketException { return delegate.getKeepAlive(); } @Override public InetAddress getLocalAddress() { return delegate.getLocalAddress(); } @Override public int getLocalPort() { return delegate.getLocalPort(); } @Override public SocketAddress getLocalSocketAddress() { return delegate.getLocalSocketAddress(); } @Override public boolean getOOBInline() throws SocketException { return delegate.getOOBInline(); } @Override public OutputStream getOutputStream() throws IOException { return delegate.getOutputStream(); } @Override public int getPort() { return delegate.getPort(); } @Override public synchronized int getReceiveBufferSize() throws SocketException { return delegate.getReceiveBufferSize(); } @Override public SocketAddress getRemoteSocketAddress() { return delegate.getRemoteSocketAddress(); } @Override public boolean getReuseAddress() throws SocketException { return delegate.getReuseAddress(); } @Override public synchronized int getSendBufferSize() throws SocketException { return delegate.getSendBufferSize(); } @Override public int getSoLinger() throws SocketException { return delegate.getSoLinger(); } @Override public synchronized int getSoTimeout() throws SocketException { return delegate.getSoTimeout(); } @Override public boolean getTcpNoDelay() throws SocketException { return delegate.getTcpNoDelay(); } @Override public int getTrafficClass() throws SocketException { return delegate.getTrafficClass(); } @Override public boolean isBound() { return delegate.isBound(); } @Override public boolean isClosed() { return delegate.isClosed(); } @Override public boolean isConnected() { return delegate.isConnected(); } @Override public boolean isInputShutdown() { return delegate.isInputShutdown(); } @Override public boolean isOutputShutdown() { return delegate.isOutputShutdown(); } @Override public void sendUrgentData(int value) throws IOException { delegate.sendUrgentData(value); } @Override public void setKeepAlive(boolean keepAlive) throws SocketException { delegate.setKeepAlive(keepAlive); } @Override public void setOOBInline(boolean oobinline) throws SocketException { delegate.setOOBInline(oobinline); } @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth); } @Override public synchronized void setReceiveBufferSize(int size) throws SocketException { delegate.setReceiveBufferSize(size); } @Override public void setReuseAddress(boolean reuse) throws SocketException { delegate.setReuseAddress(reuse); } @Override public synchronized void setSendBufferSize(int size) throws SocketException { delegate.setSendBufferSize(size); } @Override public void setSoLinger(boolean on, int timeout) throws SocketException { delegate.setSoLinger(on, timeout); } @Override public synchronized void setSoTimeout(int timeout) throws SocketException { delegate.setSoTimeout(timeout); } @Override public void setTcpNoDelay(boolean on) throws SocketException { delegate.setTcpNoDelay(on); } @Override public void setTrafficClass(int value) throws SocketException { delegate.setTrafficClass(value); } @Override public void shutdownInput() throws IOException { delegate.shutdownInput(); } @Override public void shutdownOutput() throws IOException { delegate.shutdownOutput(); } @Override public String toString() { return delegate.toString(); } @Override public boolean equals(Object o) { return delegate.equals(o); } } } 

    Hauptklasse :

     URL url = new URL("https://www.example.com/test.png"); URLConnection l_connection = null; SSLContext sslcontext = SSLContext.getInstance("TLSv1.2"); sslcontext.init(null, null, null); SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); 

    Als ich diesen Fehler bekam, lag es daran, dass die vom Server unterstützten Protokolle (TLS-Versionen) und / oder Cipher Suites nicht auf dem Gerät aktiviert (und möglicherweise nicht einmal unterstützt) wurden. Für API 16-19 werden TLSv1.1 und TLSv1.2 unterstützt, aber nicht standardmäßig aktiviert. Sobald ich sie für diese Versionen aktiviert habe, habe ich immer noch den Fehler erhalten, da diese Versionen keine der Verschlüsselungen auf unserer Instanz von AWS CloudFront unterstützen.

    Da es nicht möglich ist, Verschlüsselungen zu Android hinzuzufügen, mussten wir unsere CloudFront-Version von TLSv1.2_2018 auf TLSv1.1_2016 umstellen (was TLSv1.2 immer noch unterstützt; es ist einfach nicht erforderlich), von dem vier der Verschlüsselungen unterstützt werden die früheren Android-Versionen, von denen zwei noch immer als stark angesehen werden.

    An diesem Punkt verschwand der Fehler und die Aufrufe gingen durch (mit TLSv1.2), weil es mindestens ein Protokoll und mindestens eine Chiffre gab, die das Gerät und der Server gemeinsam benutzten.

    Sehen Sie in den Tabellen auf dieser Seite nach, welche Protokolle und Verschlüsselungen von welchen Android-Versionen unterstützt und aktiviert werden.

    Jetzt versuchte Android wirklich, SSLv3 zu benutzen, wie durch den “sslv3 Alarm-Händedruckausfall” Teil der Fehlermeldung angedeutet? Ich bezweifle das; Ich vermute, dass dies ein altes Spinnennetz in der SSL-Bibliothek ist, das nicht gereinigt wurde, aber ich kann es nicht sicher sagen.

    Um TLSv1.2 (und TLSv1.1) zu aktivieren, war ich in der Lage, eine viel einfachere SSLSocketFactory als die, die man woanders gesehen hat (wie NoSSLv3SocketFactory ). Es stellt lediglich sicher, dass die aktivierten Protokolle alle unterstützten Protokolle enthalten und dass die aktivierten Verschlüsselungen alle unterstützten Verschlüsselungen enthalten (Letzteres war für mich nicht notwendig, könnte aber für andere gelten) – siehe configure() unten. Wenn Sie nur die neuesten Protokolle socket.supportedProtocols arrayOf("TLSv1.1", "TLSv1.2") , können Sie socket.supportedProtocols durch etwas wie arrayOf("TLSv1.1", "TLSv1.2") (ebenfalls für die Verschlüsselungen):

     class TLSSocketFactory : SSLSocketFactory() { private val socketFactory: SSLSocketFactory init { val sslContext = SSLContext.getInstance("TLS") sslContext.init(null, null, null) socketFactory = sslContext.socketFactory } override fun getDefaultCipherSuites(): Array { return socketFactory.defaultCipherSuites } override fun getSupportedCipherSuites(): Array { return socketFactory.supportedCipherSuites } override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket { return configure(socketFactory.createSocket(s, host, port, autoClose) as SSLSocket) } override fun createSocket(host: String, port: Int): Socket { return configure(socketFactory.createSocket(host, port) as SSLSocket) } override fun createSocket(host: InetAddress, port: Int): Socket { return configure(socketFactory.createSocket(host, port) as SSLSocket) } override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket { return configure(socketFactory.createSocket(host, port, localHost, localPort) as SSLSocket) } override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket { return configure(socketFactory.createSocket(address, port, localAddress, localPort) as SSLSocket) } private fun configure(socket: SSLSocket): SSLSocket { socket.enabledProtocols = socket.supportedProtocols socket.enabledCipherSuites = socket.supportedCipherSuites return socket } }