Habilitación de protocolos SSL específicos con Android WebViewClient

Mi aplicación usa WebViewClient para hacer conexiones SSL al servidor. El servidor está configurado para aceptar solo protocolos TLSv1.1 y superiores.

1) ¿Cómo puedo verificar qué protocolos SSL son a) compatibles yb) habilitados de manera predeterminada cuando se usa Android WebViewClient en un dispositivo.
2) ¿Cómo habilito los protocolos SSL específicos para la instancia de Android WebViewClient utilizada en mi aplicación?

En uno de los dispositivos de prueba con Android 4.3, WebViewClient lanza la callback en ReceivedError con la descripción “Falló al realizar el protocolo de enlace SSL”
Los registros de Chrome son los siguientes:
01-29 15: 58: 00.073 5486 5525 W chromium_net: external / chromium / net / http / http_stream_factory_impl_job.cc: 865: [0129/155800: ADVERTENCIA: http_stream_factory_impl_job.cc (865)] Volviendo a SSLv3 porque el host es intolerante a TLS : 10.209.126.125:443 01-29 15: 58: 00.083 5486 5525 E chromium_net: external / chromium / net / socket / ssl_client_socket_openssl.cc: 792: [0129/155800: ERROR: ssl_client_socket_openssl.cc (792)] error de handshake; devuelto 0, código de error SSL 5, net_error -107

Mi aplicación también usa las clases HttpClient y HttpsUrlConnection para configurar las conexiones SSL. Pude usar SSLSocket API para habilitar protocolos específicos al usar estas clases. http://developer.android.com/reference/javax/net/ssl/SSLSocket.html#setEnabledProtocols (java.lang.String [])

Necesito hacer lo mismo con WebViewClient.

    Según la documentación, NO es posible admitir TLS 1.0 en WebView en Android <4.3. Para Android 4.4 está deshabilitado de forma predeterminada.

    Consulte esta tabla para obtener soporte de TLS 1.0 en diferentes navegadores: https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers

    Si su aplicación está usando, o está dispuesto a usar, los servicios de Google Play, puede usar funciones de seguridad más nuevas en teléfonos más antiguos instalando su Provider . Es fácil de instalar, solo una línea (más manejo de excepciones, etc.). También necesitará agregar servicios de google play a su archivo gradle si aún no lo tiene. ProviderInstaller está incluido en el paquete -base .

     try { ProviderInstaller.installIfNeeded(this); } catch (GooglePlayServicesRepairableException e) { // Fix it } catch (GooglePlayServicesNotAvailableException e) { // Skip it } 

    Para ver un ejemplo completo, consulte “Actualización de su proveedor de seguridad para protegerse de vulnerabilidades SSL” de Google.

    En realidad, logré que funcione, pero necesitas una biblioteca okHttp para eso. Pruebe esto cuando configure la actividad del navegador:

      WebViewClient client = new WebViewClient() { private OkHttpClient okHttp = new OkHttpClient.Builder().build(); @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { Request okHttpRequest = new Request.Builder().url(url).build(); try { Response response = okHttp.newCall(okHttpRequest).execute(); return new WebResourceResponse(response.header("Content-Type", "plain/text"), response.header("Content-Encoding", "deflate"), response.body().byteStream()); } catch (IOException e) { e.printStackTrace(); } return null; } }; webView.setWebViewClient(client); 

    Además, necesitará el administrador de confianza clásico Manipulator, la fábrica de sockets SSL y su implementación en su clase de aplicación:

     public class TrustManagerManipulator implements X509TrustManager { private static TrustManager[] trustManagers; private static final X509Certificate[] acceptedIssuers = new X509Certificate[] {}; public boolean isClientTrusted(X509Certificate[] chain) { return true; } public boolean isServerTrusted(X509Certificate[] chain) { return true; } public static void allowAllSSL() { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); SSLContext context = null; if (trustManagers == null) { trustManagers = new TrustManager[] { new TrustManagerManipulator() }; } try { context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, new SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultSSLSocketFactory(context .getSocketFactory()); } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return acceptedIssuers; } } 

    SSl Socket Factory:

     public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] managers = new TrustManager[] { new TrustManagerManipulator() }; context.init(null, managers, new SecureRandom()); 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.1", "TLSv1.2"}); } return socket; } } 

    Clase de aplicación:

     public class App extends Application { private static App appInstance; @Override public void onCreate() { super.onCreate(); setupSSLconnections(); } private void setupSSLconnections() { try { HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); } catch (KeyManagementException | NoSuchAlgorithmException e) { e.printStackTrace(); } } } 

    es beause android 4.3 no es compatible con TSL 1.1 pero solo TSL1.0 lee este artículo https://www.ssllabs.com/ssltest/clients.html find android 4.3 se verá

    Protocolos TLS 1.3 Sin TLS 1.2 Sin TLS 1.1 Sin TLS 1.0 Sí SSL 3 INSEGURA Sí SSL 2 No