Javax.net.ssl.SSLHandshakeException: Handshake falló en Android 5.0.0 cuando SSLv2 y SSlv3 están deshabilitados (sólo TLS) (y mayores)

Este es mi primer post y voy a tratar de hacer lo mejor para ser lo más claro posible (lo siento por mi inglés).

Aquí está mi problema, estoy usando retrofit: 1.9.0 y okhttp: 2.7.5 para realizar la llamada API. Todo estaba bien hasta que mi proveedor de servidor deshabilitar SLLv2 y SSLv3 causa de sercurity problema (ahogar fallar encontrado el primero de marzo).

Ahora compruebo la información sobre mi abastecedor y él permite solamente TLSv1 con cypher (TLS 1.0 TLS_RSA_WITH_3DES_EDE_CBC_SHA ningún FS) de https://www.ssllabs.com/ .

Ok, así que esto es todas las pruebas que he hecho y los resultados:

[ACTUALIZACIÓN DEL PROBLEMA SOLUCIONADO]

Encontrar una manera de resolver este problema en mi segunda respuesta.

ACTUALIZACIÓN Parece que los problemas provienen de la versión de Google API. Cuando pruebo en API 18 todo está funcionando bien. Cuando está en Android greather o igual a 5.0.0 falla.

Primer examen

Conf. resumen:

  • CompileSdkVersion 23
  • BuildToolsVersion '23 .0.2 '
  • MinSdkVersion 18
  • TargetSdkVersion 21
  • Retrofit: 1.9.0
  • Okhttp: 2.7.5
  • Versión de Android> 5.0.0 (pero es igual en todos los dispositivos …)

Rest Client (LoginRestClient):

public class LoginRestClient { private static final String BASE_URL = ""; private LoginApiService apiService; public LoginRestClient() { Gson gson = new GsonBuilder() .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'") .create(); RestAdapter restAdapter = new RestAdapter.Builder() .setLogLevel(RestAdapter.LogLevel.FULL) .setEndpoint(ApiIntentService.getHostAddress()) .setConverter(new GsonConverter(gson)) .setClient(new OkClient(ApiIntentService.getConnectionHttpClient())) .build(); apiService = restAdapter.create(LoginApiService.class); } public LoginApiService getApiService() { return apiService; } } 

Función para crear cliente OkHttpClient getConnectionHttpClient ()

 public static OkHttpClient getConnectionHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setReadTimeout(60, TimeUnit.SECONDS); okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS); ConnectionSpec specs = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) .tlsVersions(TlsVersion.TLS_1_0) .cipherSuites(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA) .build(); okHttpClient.setConnectionSpecs(Collections.singletonList(specs)); return okHttpClient; } 

Resultado en el error void público (error RetrofitError) de CallBack personalizado

Java.net.UnknownServiceException: No se pueden encontrar protocolos aceptables. = Protocolos soportados = [SSLv3, TLSv1, TLSv1.1, TLSv1.2]], protocolos soportados = [TLSv1, TLSv1, TLSv1.2, TLSv1.2]

Segunda prueba

He hecho un SSLSocketFactory personalizado para deshabilitar SSLv3 y forzar TLS:

 /** * @author fkrauthan */ public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() 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(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"}); } return socket; } } 

Lo uso así:

 public static OkHttpClient getConnectionHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setReadTimeout(60, TimeUnit.SECONDS); okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS); try { TLSSocketFactory tlsSocketFactory = new TLSSocketFactory(); HttpsURLConnection.setDefaultSSLSocketFactory(tlsSocketFactory); okHttpClient.setSslSocketFactory(tlsSocketFactory); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return okHttpClient; } 

Resultado en el error void público (error RetrofitError) de CallBack personalizado

Javax.net.ssl.SSLProtocolException: Protocolo de seguridad SSL abortado: ssl = 0x7f87885280: Error en la biblioteca SSL, normalmente un error de error de protocolo: 14077410: Rutinas SSL: SSL23_GET_SERVER_HELLO: fallo de handshake de alerta sslv3 (external / openssl / ssl / s23_clnt.c: 770) 0x7f87c2fdf0: 0x00000000)

Si alguien puede ayudarme, será muy cool. Todas mis aplicaciones están abajo y estoy luchando contra este problema desde ayer por la mañana para restaurar mis servicios. Estoy quitando el pelo uno por uno …

Gracias por adelantado.

PROBLEMA RESUELTO:

Hola a todos después de pelear durante 3 días y noches aquí es la solución final. Así que gracias a la solución aquí:

Cómo deshabilitar SSLv3 en android para HttpsUrlConnection?

Y esta biblioteca: https://guardianproject.info/code/netcipher

Permite proporcionar a Android una mejor manera de trabajar con cypher y TLS en caso de que SSLv2 y SSlv3 estén desactivados.

Primero crear esta clase NoSSLv3SocketFactory.java y acoplar esto con una conexión CypherUrl creando un constructor como este

 public NoSSLv3SocketFactory(URL sourceUrl) throws IOException { this.delegate = NetCipher.getHttpsURLConnection(sourceUrl).getDefaultSSLSocketFactory(); } 

NoSSLv3SocketFactory.java (código completo)

 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.net.URL; 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; import info.guardianproject.netcipher.NetCipher; public class NoSSLv3SocketFactory extends SSLSocketFactory{ private final SSLSocketFactory delegate; public NoSSLv3SocketFactory(URL sourceUrl) throws IOException { this.delegate = NetCipher.getHttpsURLConnection(sourceUrl).getDefaultSSLSocketFactory(); } 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<String> enabledProtocols = new ArrayList<String>(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); } } } 

Y ahora (en mi caso con retrofit) sólo lo utilizan de esta manera:

Así que primero, agregue un método estático (o como quiera crearlo en uso) para hacer un okHttpClient con nuestra clase NoSSlv3Factory.java previamente creada.

 public static OkClient createClient(int readTimeout, TimeUnit readTimeoutUnit, int connectTimeout, TimeUnit connectTimeoutUnit) { final OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setReadTimeout(readTimeout, readTimeoutUnit); okHttpClient.setConnectTimeout(connectTimeout, connectTimeoutUnit); try { URL url = new URL(ApiIntentService.getHostAddress()); SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(url); okHttpClient.setSslSocketFactory(NoSSLv3Factory); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return new OkClient(okHttpClient); } 

Entonces , en mi caso cuando usted crea su RestAdapter apenas lo hace como esto, y no olvide fijarle cliente.

 public class LoginRestClient { private static final String BASE_URL = ""; private LoginApiService apiService; public LoginRestClient() { Gson gson = new GsonBuilder() .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'") .create(); RestAdapter restAdapter = new RestAdapter.Builder() .setLogLevel(RestAdapter.LogLevel.FULL) .setEndpoint(ApiIntentService.getHostAddress()) .setConverter(new GsonConverter(gson)) .setClient(ApiIntentService.createClient(60, TimeUnit.SECONDS, 20, TimeUnit.SECONDS)) .build(); apiService = restAdapter.create(LoginApiService.class); } public LoginApiService getApiService() { return apiService; } } 

Con esto debe estar funcionando. Espero que sea útil para alguien más.

  • ¿Cómo puedo hacer que Android Volley realice una solicitud HTTPS, utilizando un certificado autofirmado por una CA de Unkown?
  • ProGuard causa error de handshake SSL en Android
  • Android Habilitar TLSv1.2 en OKHttp
  • Comprobación de que el mensaje provenía de un punto específico de aplicación / punto final
  • Vimeo error de SSL con Retrofit en Android
  • Android se conecta al servidor con certificado autenticado
  • Android - Https conexión a un servicio WCF de .NET da SSLException: "Ningún certificado de compañero"
  • Com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: Protocolo SSL abortado:
  • Error de lectura: error en la biblioteca SSL, generalmente un error de protocolo
  • Habilitación de protocolos SSL específicos con Android WebViewClient
  • El certificado StartSSL no es de confianza en Firefox y en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.