java - secure - sslcontext android example
SSLHandshakeException mientras se conecta a un sitio https (1)
SSLlabs aparentemente está probando el soporte "listo para usar". La criptografía de Java tiene una antigüedad que se remonta a la década de 1990 cuando el gobierno de los EE. UU. Restringió severamente la exportación de software criptográfico, y como resultado, el JRE (o JDK) distribuido por el entonces Sun ahora-Oracle no permite el uso de cifrado simétrico de 256 bits , que su servidor es exigente. Debe descargar e instalar los "Archivos de política de jurisdicción de fuerza ilimitada JCE " para su versión Java (principal); 8 está en http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html . El archivo README en el archivo proporciona detalles largos, pero básicamente reemplaza dos pequeños archivos jar en JRE / lib / security.
TLSv1.2 no es un problema real ahora . El protocolo TLS negocia automáticamente la versión más alta admitida (y habilitada) por ambos extremos. Java 8 implementa SSLv3, TLSv1.0, TLSv1.1 y TLSv1.2, pero las actualizaciones recientes (8u31 o 7u75 y posteriores) deshabilitan SSLv3 de forma predeterminada debido a POODLE; puede volver a habilitarlo si lo desea, pero debe ser reacio a hacerlo. (Java 7 implementa las mismas versiones de protocolo, pero el cliente deshabilita por defecto 1.1 y 1.2 debido a problemas de compatibilidad en su lanzamiento hace varios años).
Sin embargo, debido a POODLE y BEAST, algunas autoridades de seguridad ya no aceptan SSLv3 y TLSv1.0 como lo suficientemente seguro; Un ejemplo importante son las tarjetas de crédito y débito, como se detalla en https://security.stackexchange.com/a/87077/39571 . TLSv1.2 incluye algunas mejoras técnicas sobre 1.1, haciéndolo preferido hoy, y puede haber descubrimientos futuros que hagan que esas mejoras sean cruciales; si su servidor no puede soportar 1.2 (y tal vez más) en ese punto , estaría en problemas. Del mismo modo, el hecho de que el único conjunto de aplicaciones admitidas del servidor utilice el intercambio de claves RSA simple, es decir, NO el secreto de reenvío, se considera subóptimo ahora y con el tiempo puede volverse inaceptable.
keytool (al menos con los archivos de almacén de claves y almacén de confianza utilizados normalmente) no tiene nada que ver con la criptografía simétrica. Probablemente podría ser relevante si el servidor utiliza una raíz de CA (o más exactamente y un poco más general, ancla de confianza) en la que su JRE y / o aplicación no confía, y / o si el servidor desea la autenticación del cliente a nivel SSL / TLS , Lo cual es bastante raro. (La mayoría de los sitios web se autentican a nivel de aplicación web, o al menos a nivel HTTP, si es que lo hacen). La comprobación de SSLLabs de la cadena de certificados del servidor (y varias otras cosas también) es generalmente más estricta que la de Java, y no se quejaron de eso. área, por lo que es poco probable que tenga un problema allí.
Estoy tratando de grabar un sitio https a través de jmeter (versión 2.13, versión java - 1.8u31) y obtengo SSLHandshakeException mientras me conecto a un sitio https. El mensaje de error es
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2011)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:436)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.jmeter.protocol.http.sampler.MeasuringConnectionManager$MeasuredConnection.open(MeasuringConnectionManager.java:107)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeRequest(HTTPHC4Impl.java:517)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:331)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146)
at org.apache.jmeter.protocol.http.proxy.Proxy.run(Proxy.java:240)
He activado el registro de depuración para SSL pero no pude entender la causa raíz. Parece que el cliente Java envía ClientHello pero no recibe el mensaje ServerHello ( where el servidor elige la versión más alta de SSL y la mejor suite de cifrado que el cliente y el servidor admiten y envía esta información al cliente). Veo diferencias entre las versiones de protocolo que envía, lee y recibe el cliente (TLSv1.1 vs TLSv1.2)
¿Es esta la causa raíz? Si es así, ¿cómo puedo solucionarlo?
Los registros se pegan aquí - Java SSLHandshakeException Logs - Pastebin.com
Actualizar
Como sugirió @Anand Bhatt, analicé el sitio con ssllabs y entendí lo siguiente
- El servidor no es compatible con TLSv1.2, que es compatible con Java 8
- El servidor solo admite un conjunto de cifrado: TLS_RSA_WITH_AES_256_CBC_SHA
- Java 8u31 no es compatible con el conjunto de cifrado que admite el servidor y ese es probablemente el problema.
¿Eso suena bien? Si es así, ¿cómo hacemos que el cliente java 8 sea compatible con el conjunto de cifrado que admite el servidor?