studio significa que not found for example conexion certpathvalidatorexception certification certificado cert java android ssl jsse httpsurlconnection

java - significa - ¿Cómo anular la lista de cifrado enviada al servidor por Android al usar HttpsURLConnection?



ssl pinning android (3)

Durante la negociación de TLS, los clientes envían una lista de cifrados admitidos al servidor, el servidor elige uno y se inicia el cifrado. Quiero cambiar esta lista de cifrado enviada al servidor por Android, cuando estoy usando HttpsURLConnection para la comunicación.

Sé que puedo usar setSSLSocketFactory en el objeto HttpsURLConnection para configurarlo y usar un SSLSocketFactory . Esto es útil cuando quiero cambiar el administrador de confianza, etc. utilizado por el SSLSocket devuelto por SSLSocketFactory .

Sé que, en general, esta lista de cifrados puede editarse utilizando un objeto SSLParameters y pasándoselo a los objetos SSlsocket o SSLEngine utilizando los métodos que proporcionan.

¡PERO el SSLSocketFactory no parece exponer tales métodos!

No puedo encontrar una manera de cambiar los SSLParameters de los objetos SSLSocket devueltos creados por SSLSocketFactory que paso a HttpsURLConnection .

¿Qué hacer?

Supongo que esto también es relevante para Java en general, no solo para Android. Tal vez haya una manera OO de hacerlo (por ejemplo, extienda SSLSocketFactory y proporcione eso a HttpsURLConnection ?)


Este código funcionó de maravilla para una inesperada javax.net.ssl.SSLHandshakeException .

La actualización a jdk1.8.0_92 y los archivos de política de fuerza ilimitada de Oracle JCE no ayudaron, y no logré aplicar SSLParameters específicos a HttpsUrlConnection .

En particular, el intento de utilizar HttpsUrlConnection para leer https://www.adrbnymellon.com da como resultado el siguiente error:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Este sitio web funcionó bien antes del 15/04/2016 y luego comenzó a fallar. Creo que la falla se debe a que el sitio web dejó de admitir SSLv2Hello y SSLv3 debido a la vulnerabilidad DROWN. Mira esto para un gran análisis.

El acceso al sitio web comenzó a funcionar modificando el código con solo 2 constantes:

private static final String PREFERRED_CIPHER_SUITE = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; SSLContext context = SSLContext.getInstance("TLSv1.2");

Espero que esto ayude a alguien más.


Este fragmento de código es un poco crudo. por favor, use con cuidado.

public class PreferredCipherSuiteSSLSocketFactory extends SSLSocketFactory { private static final String PREFERRED_CIPHER_SUITE = "TLS_RSA_WITH_AES_128_CBC_SHA"; private final SSLSocketFactory delegate; public PreferredCipherSuiteSSLSocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return setupPreferredDefaultCipherSuites(this.delegate); } @Override public String[] getSupportedCipherSuites() { return setupPreferredSupportedCipherSuites(this.delegate); } @Override public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException { Socket socket = this.delegate.createSocket(arg0, arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0, int arg1) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } private static String[] setupPreferredDefaultCipherSuites(SSLSocketFactory sslSocketFactory) { String[] defaultCipherSuites = sslSocketFactory.getDefaultCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(defaultCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0, PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } private static String[] setupPreferredSupportedCipherSuites(SSLSocketFactory sslSocketFactory) { String[] supportedCipherSuites = sslSocketFactory.getSupportedCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(supportedCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0, PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } }

Cuando quieres usarlo

HttpsURLConnection connection = (HttpsURLConnection) (new URL(url)) .openConnection(); SSLContext context = SSLContext.getInstance("TLS"); TrustManager tm[] = {new SSLPinningTrustManager()}; context.init(null, tm, null); SSLSocketFactory preferredCipherSuiteSSLSocketFactory = new PreferredCipherSuiteSSLSocketFactory(context.getSocketFactory()); connection.setSSLSocketFactory(preferredCipherSuiteSSLSocketFactory); connection.connect();

Gracias.


Incluí la técnica en la respuesta 1 de @ ThinkChris en una llamada a un método simple muerto. Puede usar la biblioteca de NetCipher para obtener una configuración de TLS moderna al usar HttpsURLConnection de Android. NetCipher configura la instancia de HttpsURLConnection para usar la mejor versión compatible de TLS, elimina la compatibilidad con SSLv3 y configura el mejor conjunto de cifras para esa versión de TLS. Primero, agrégalo a tu build.gradle :

compile ''info.guardianproject.netcipher:netcipher:1.2''

O puede descargar netcipher-1.2.jar e incluirlo directamente en su aplicación. Entonces, en lugar de llamar:

HttpURLConnection connection = (HttpURLConnection) sourceUrl.openConnection();

Llama esto:

HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl);

Si desea personalizar específicamente esa lista de cifrado, puede verificar el código allí. Pero la mayoría de la gente no debería tener que pensar en la lista de cifrado, sino que debe usar las mejores prácticas comunes por defecto.