Cómo utilizar HttpClient con cualquier certificado SSL, no importa lo "malo" que es

Parques Brad:

Estoy usando Apache HttpClient en un rastreador web que es única para el rastreo de datos públicas.

Me gustaría que fuera capaz de sitios de rastreo con certificados válidos, no importa cuán válido.

Mi rastreador no estará pasando en cualquier nombre de usuario, contraseñas, etc y no hay datos sensibles se están enviando o recibiendo.

Para este caso de uso, Me arrastraría la httpversión de un sitio si es que existe, pero a veces no lo hace, por supuesto.

¿Cómo se puede hacer esto con Apache de HttpClient ?

Probé algunas sugerencias como éste , pero todavía fallan por algunos certs no válidos, por ejemplo:

failed for url:https://dh480.badssl.com/, reason:java.lang.RuntimeException: Could not generate DH keypair
failed for url:https://null.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://rc4-md5.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://rc4.badssl.com/, reason:Received fatal alert: handshake_failure
failed for url:https://superfish.badssl.com/, reason:Connection reset

Tenga en cuenta que he intentado esto con mi $JAVA_HOME/jre/lib/security/java.securitydel archivo de jdk.tls.disabledAlgorithmsconjunto a la nada, para asegurar que esto no era un problema, y todavía consigo fracasos como el de arriba.

user3474985:

La respuesta corta a su pregunta, que es confiar en concreto todos los CERT, sería utilizar la TrustAllStrategy y hacer algo como esto:

SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustAllStrategy());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
        sslContextBuilder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
        socketFactory).build();

Sin embargo ... un certificado no válido no puede ser su principal problema. Un handshake_failure puede ocurrir por varias razones, pero en mi experiencia por lo general es debido a un SSL / TLS versión desajuste o falta de negociación conjunto de cifrado. Esto no significa que el certificado SSL es "malo", es sólo una falta de correspondencia entre el servidor y el cliente. Se puede ver exactamente donde el apretón de manos está fallando el uso de una herramienta como Wireshark ( más sobre esto )

Mientras Wireshark puede ser grande para ver dónde está fallando, no va a ayudar a llegar a una solución. Siempre que he ido sobre la depuración handshake_failures en el pasado he encontrado que esta herramienta particularmente útil: https://testssl.sh/

Se puede señalar que la escritura en cualquiera de sus sitios web no aprender más acerca de qué protocolos están disponibles en ese objetivo y cuáles son sus necesidades de los clientes al apoyo con el fin de establecer un apretón de manos con éxito. Además, puede imprimir información sobre el certificado.

Por ejemplo (mostrando sólo dos secciones de la salida de testssl.sh):

./testssl.sh www.google.com
....
 Testing protocols (via sockets except TLS 1.2, SPDY+HTTP2) 

 SSLv2               not offered (OK)
 SSLv3               not offered (OK)
 TLS 1               offered
 TLS 1.1             offered
 TLS 1.2             offered (OK)
 ....
Server Certificate #1
   Signature Algorithm          SHA256 with RSA
   Server key size              RSA 2048 bits
   Common Name (CN)             "www.google.com"
   subjectAltName (SAN)         "www.google.com" 
   Issuer                       "Google Internet Authority G3" ("Google Trust Services" from "US")
   Trust (hostname)             Ok via SAN and CN (works w/o SNI)
   Chain of trust               "/etc/*.pem" cannot be found / not readable
   Certificate Expiration       expires < 60 days (58) (2018-10-30 06:14 --> 2019-01-22 06:14 -0700)
 ....
 Testing all 102 locally available ciphers against the server, ordered by encryption strength 
(Your /usr/bin/openssl cannot show DH/ECDH bits)

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.  Encryption Bits
------------------------------------------------------------------------
xc030   ECDHE-RSA-AES256-GCM-SHA384       ECDH       AESGCM    256       
xc02c   ECDHE-ECDSA-AES256-GCM-SHA384     ECDH       AESGCM    256       
xc014   ECDHE-RSA-AES256-SHA              ECDH       AES       256       
xc00a   ECDHE-ECDSA-AES256-SHA            ECDH       AES       256       
x9d     AES256-GCM-SHA384                 RSA        AESGCM    256       
x35     AES256-SHA                        RSA        AES       256       
xc02f   ECDHE-RSA-AES128-GCM-SHA256       ECDH       AESGCM    128       
xc02b   ECDHE-ECDSA-AES128-GCM-SHA256     ECDH       AESGCM    128       
xc013   ECDHE-RSA-AES128-SHA              ECDH       AES       128       
xc009   ECDHE-ECDSA-AES128-SHA            ECDH       AES       128       
x9c     AES128-GCM-SHA256                 RSA        AESGCM    128       
x2f     AES128-SHA                        RSA        AES       128       
x0a     DES-CBC3-SHA                      RSA        3DES      168 

Así, utilizando esta salida podemos ver que si su cliente sólo se admite SSLv3, el apretón de manos fracasaría debido a que el protocolo no es compatible con el servidor. La oferta de protocolo es poco probable que el problema, pero se puede comprobar el doble de lo que admite su cliente Java obteniendo la lista de protocolos habilitados. Puede proporcionar una implementación sobrescrito de la SSLConnectionSocketFactory desde arriba fragmento de código para obtener la lista de protocolos habilitados / compatibles y paquetes de cifrado de la siguiente manera ( SSLSocket ):

class MySSLConnectionSocketFactory extends SSLConnectionSocketFactory {
    @Override
    protected void prepareSocket(SSLSocket socket) throws IOException {
        System.out.println("Supported Ciphers" + Arrays.toString(socket.getSupportedCipherSuites()));
        System.out.println("Supported Protocols" + Arrays.toString(socket.getSupportedProtocols()));
        System.out.println("Enabled Ciphers" + Arrays.toString(socket.getEnabledCipherSuites()));
        System.out.println("Enabled Protocols" + Arrays.toString(socket.getEnabledProtocols()));
    }
}

A menudo me encuentro handshake_failure cuando hay un fallo de cifrado Negociación de conjunto. Para evitar este error, la lista de su cliente de conjuntos de cifrado soportados debe contener al menos un partido a un conjunto de cifrado de la lista de conjuntos de cifrado compatibles del servidor.

Si el servidor requiere cifrado basado AES256 es probable que tenga las extensiones criptográficas Java (JCE). Estas bibliotecas son nación restringido por lo que no pueden estar disponibles para alguien fuera de los EE.UU..

Más acerca de las restricciones de criptografía, si está interesado: https://crypto.stackexchange.com/questions/20524/why-there-are-limitations-on-using-encryption-with-keys-beyond-certain-length

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=180949&siteId=1
Recomendado
Clasificación