java - verified - retrofit ssl pinning
Habilitación de protocolos SSL específicos con Android WebViewClient (4)
En realidad, logré hacerlo funcionar, pero necesitas la 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 clásico manipulador Trust Manager, 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;
}
}
Fábrica de enchufes SSl:
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();
}
}
}
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 verifico qué protocolos SSL son a) compatibles yb) habilitados de manera predeterminada cuando uso Android WebViewClient en un dispositivo?
2) ¿Cómo habilito protocolos SSL específicos para la instancia de Android WebViewClient utilizada en mi aplicación?
En uno de los dispositivos de prueba que ejecutan Android 4.3, WebViewClient lanza la devolución de llamada ReceivedError con la descripción "Error 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: externo / 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)]
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 este cuadro para ver el soporte de TLS 1.0 en diferentes navegadores: https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers
Si su aplicación está utilizando, o está dispuesto a utilizar, los servicios de Google Play, puede utilizar las funciones de seguridad más recientes 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 contra exploits SSL" de Google.
es porque 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 verá
Protocolos TLS 1.3 No TLS 1.2 No TLS 1.1 No TLS 1.0 Sí SSL 3 INSECURE Sí SSL 2 No