java - verified - HTTPS GET(SSL) con Android y certificado de servidor autofirmado
retrofit ssl pinning (7)
He revisado varias publicaciones sobre cómo recuperar algo a través de HTTPS
en Android, desde un servidor que usa un certificado autofirmado. Sin embargo, ninguno de ellos parece funcionar; todos fallan en eliminar el
javax.net.ssl.SSLException: mensaje de certificado de servidor no confiable.
No es una opción modificar el servidor para que tenga un certificado confiable, y tampoco es una opción hacer que el certificado del servidor coincida con la dirección IP del servidor.
Tenga en cuenta que el servidor no tendrá un nombre DNS, solo tendrá una dirección IP. La solicitud GET se ve así:
https://username:password@anyIPAddress/blabla/index.php?param=1¶m2=3
Soy plenamente consciente de que esta solución es propensa a ataques de hombre en el medio, etc.
Por lo tanto, la solución debe ignorar la falta de confianza en el certificado e ignorar la falta de coincidencia del nombre de host.
¿Alguien sabe el código, que hace esto, usando Java para Android?
Hay muchos intentos de explicar esto en stackoverflow.com , y muchos fragmentos de código, pero parece que no funcionan, y nadie ha proporcionado un bloque de código que resuelva esto, hasta donde puedo ver. Sería interesante saber si alguien realmente resolvió esto, o si Android simplemente bloquea certificados que no son de confianza.
Como señala correctamente, hay dos problemas: a) el certificado no es de confianza, yb) el nombre en el certificado no coincide con el nombre de host.
ADVERTENCIA: para cualquier otra persona que llegue a esta respuesta, este es un truco sucio y horrible y no debe usarlo para nada que importe. SSL / TLS sin autenticación es peor que ningún cifrado en absoluto: leer y modificar sus datos "encriptados" es trivial para un atacante y ni siquiera sabría que estaba sucediendo .
¿Aún conmigo? Temía que sí ...
a) se resuelve creando un SSLContext personalizado cuyo TrustManager acepta algo:
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
}
}, null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
y b) creando un HostnameVerifier que permite que la conexión continúe aunque el certificado no coincida con el nombre de host:
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
Ambos deben suceder justo al comienzo de su código, antes de empezar a jugar con HttpsURLConnections, etc. Esto funciona tanto en Android como en el JRE regular. Disfrutar.
Hice una aplicación que usa autofirmados o confía en todos los certs. La fuente está aquí: http://code.google.com/p/meneameandroid/source/browse/#svn/trunk/src/com/dcg/auth y de uso gratuito: P
Simplemente use HttpManager y cree la fábrica de SSL utilizando la confianza de todos: http://code.google.com/p/meneameandroid/source/browse/trunk/src/com/dcg/util/HttpManager.java
EDITAR: Enlaces actualizados
Hice una aplicación que usa el certificado autofirmado hace 4 meses. Aquí está el código. Espero que ayude: https://bitbucket.org/momo0002/tlsdemo.git
Puede hacerlo de forma segura: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
Si está utilizando un HttpsURLConnection, intente llamar a setHostnameVerifier
antes de connect()
y pasarle un HostnameVerifier
que solo acepta independientemente de la veracidad.
Si me preguntas, hazlo de forma segura.
Encontré un buen tutorial http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/ y realmente no es tan difícil de implementar.
También el tutorial recomendado por Maciek es muy bueno.
Lo probé y funciona en mi aplicación sin problemas.
Si tiene acceso a los dispositivos, puede agregar el certificado a un almacén de claves. Ver más información aquí .
Por otro lado, puedes utilizar this método, pero creo que es feo.
Recursos:
Sobre el mismo tema: