validate that not net manager error err_cert_authority_invalid does disable create chains certpathvalidatorexception certificates cert avoid all accept java ssl ssl-certificate sslhandshakeexception

java - that - Recibido alerta fatal: handshake_failure a través de SSLHandshakeException



java ssl accept all certificates (14)

Tengo un problema con la conexión SSL autorizada. Creé Struts Action que se conecta al servidor externo con el certificado SSL autorizado por el cliente. En mi acción estoy tratando de enviar algunos datos al servidor del banco, pero sin suerte, porque tengo como resultado del servidor el siguiente error:

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

Mi método de mi clase Acción que envía datos al servidor

//Getting external IP from host URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp"); BufferedReader inIP = new BufferedReader(new InputStreamReader(whatismyip.openStream())); String IPStr = inIP.readLine(); //IP as a String Merchant merchant; System.out.println("amount: " + amount + ", currency: " + currency + ", clientIp: " + IPStr + ", description: " + description); try { merchant = new Merchant(context.getRealPath("/") + "merchant.properties"); } catch (ConfigurationException e) { Logger.getLogger(HomeAction.class.getName()).log(Level.INFO, "message", e); System.err.println("error: " + e.getMessage()); return ERROR; } String result = merchant.sendTransData(amount, currency, IPStr, description); System.out.println("result: " + result); return SUCCESS;

Mi archivo merchant.properties:

bank.server.url=https://-servernameandport-/ https.cipher=-cipher- keystore.file=-key-.jks keystore.type=JKS keystore.password=-password- ecomm.server.version=2.0 encoding.source=UTF-8 encoding.native=UTF-8

Por primera vez pensé que se trataba de un problema de certificado, lo convertí de .pfx a .jks, pero tengo el mismo error, sin cambios.


El mío era un error incompatible con la versión TLS .

Anteriormente era TLSv1 Lo cambié TLSV1.2 esto resolvió mi problema.


En mi caso, pasar de jdk 1.7.0_71 a jdk 1.8.0_60 solucionó el error


Encontré un servidor HTTPS que falló de esta manera si mi proceso de cliente Java se configuró con

-Djsse.enableSNIExtension=false

La conexión falló con handshake_failure después de que ServerHello hubiera finalizado correctamente, pero antes de que comenzara la secuencia de datos.

No hubo un mensaje de error claro que identificara el problema, el error simplemente se veía como

main, READ: TLSv1.2 Alert, length = 2 main, RECV TLSv1.2 ALERT: fatal, handshake_failure %% Invalidated: [Session-3, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384] main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Aislé el problema al intentar con y sin la -Djsse.enableSNIExtension=false " -Djsse.enableSNIExtension=false "


Esto también puede suceder cuando el cliente necesita presentar un certificado. Después de que el servidor enumera la cadena de certificados, puede ocurrir lo siguiente:

3. Solicitud de certificado El servidor emitirá una solicitud de certificado del cliente. La solicitud mostrará una lista de todos los certificados que acepta el servidor.

*** CertificateRequest Cert Types: RSA Cert Authorities: <CN=blah, OU=blah, O=blah, L=blah, ST=blah, C=blah> <CN=yadda, DC=yadda, DC=yadda> <CN=moreblah, OU=moreblah, O=moreblah, C=moreblah> <CN=moreyada, OU=moreyada, O=moreyada, C=moreyada> ... the rest of the request *** ServerHelloDone

4. Cadena de certificados del cliente Este es el certificado que el cliente está enviando al servidor.

*** Certificate chain chain [0] = [ [ Version: V3 Subject: EMAILADDRESS=client''s email, CN=client, OU=client''s ou, O=client''s Org, L=client''s location, ST=client''s state, C=client''s Country Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 ... the rest of the certificate *** ClientKeyExchange, RSA PreMasterSecret, TLSv1 ... key exchange info

Si no hay un certificado en la cadena y el servidor lo requiere, obtendrá el error de saludo aquí. Una causa probable es que no se encontró la ruta a su certificado.

5. Certificado Verify El cliente le pide al servidor que verifique el certificado

*** CertificateVerify ... payload of verify check

Este paso solo ocurrirá si está enviando un certificado.

6. Finalizado El servidor responderá con una respuesta de verificación

*** Finished verify_data: { 345, ... }


Estoy usando el cliente http com.google.api. Cuando me comunico con un sitio interno de la compañía, tengo este problema cuando utilizo https por error, en lugar de http.

main, READ: TLSv1.2 Alert, length = 2 main, RECV TLSv1.2 ALERT: fatal, handshake_failure main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure main, IOException in getSession(): javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure main, called close() main, called closeInternal(true) 262 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection - Connection shut down main, called close() main, called closeInternal(true) 263 [main] DEBUG org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager - Released connection is not reusable. 263 [main] DEBUG org.apache.http.impl.conn.tsccm.ConnPoolByRoute - Releasing connection [HttpRoute[{s}->https://<I-replaced>]][null] 263 [main] DEBUG org.apache.http.impl.conn.tsccm.ConnPoolByRoute - Notifying no-one, there are no waiting threads Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:339) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123) at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147) at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) at com.google.api.client.http.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:67) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:960)


Hoy encuentro el mismo problema con el cliente OkHttp para OBTENER una URL basada en https. Fue causado por la versión del protocolo Https y el método Cipher no coincide entre el lado del servidor y el lado del cliente .

1) revise la versión del Protocolo https de su sitio web y el método Cipher.

openssl>s_client -connect your_website.com:443 -showcerts

Obtendrá mucha información detallada, la información clave se enumera de la siguiente manera:

SSL-Session: Protocol : TLSv1 Cipher : RC4-SHA 2) configure su cliente http, por ejemplo, en el caso del cliente OkHttp :

@Test() public void testHttpsByOkHttp() { ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_0) //protocol version .cipherSuites( CipherSuite.TLS_RSA_WITH_RC4_128_SHA, //cipher method CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) .build(); OkHttpClient client = new OkHttpClient(); client.setConnectionSpecs(Collections.singletonList(spec)); Request request = new Request.Builder().url("https://your_website.com/").build(); try { Response response = client.newCall(request).execute(); if(response.isSuccessful()){ logger.debug("result= {}", response.body().string()); } } catch (IOException e) { e.printStackTrace(); } }

Esto obtendrá lo que queremos.


La falla del apretón de manos pudo haber ocurrido debido a varias razones:

  • Conjuntos de cifrado incompatibles en uso por el cliente y el servidor. Esto requeriría que el cliente use (o habilite) un conjunto de cifrado que sea compatible con el servidor.
  • Versiones incompatibles de SSL en uso (el servidor puede aceptar solo TLS v1, mientras que el cliente solo puede usar SSL v3). Nuevamente, el cliente debería asegurarse de que usa una versión compatible del protocolo SSL / TLS.
  • Ruta de confianza incompleta para el certificado del servidor; el cliente probablemente no confía en el certificado del servidor. Esto normalmente daría lugar a un error más detallado, pero es bastante posible. Por lo general, la solución es importar el certificado de CA del servidor en el almacén de confianza del cliente.
  • El certificado se emite para un dominio diferente. De nuevo, esto hubiera resultado en un mensaje más detallado, pero voy a establecer la corrección aquí en caso de que esta sea la causa. La resolución en este caso sería obtener el servidor (no parece ser tuyo) para usar el certificado correcto.

Como la falla subyacente no se puede identificar, es mejor activar el -Djavax.net.debug=all para habilitar la depuración de la conexión SSL establecida. Con la depuración activada, puede identificar qué actividad en el protocolo de enlace ha fallado.

Actualizar

Según los detalles ahora disponibles, parece que el problema se debe a una ruta de confianza de certificado incompleta entre el certificado emitido al servidor y una CA raíz. En la mayoría de los casos, esto se debe a que el certificado de CA raíz está ausente en el almacén de confianza, lo que lleva a la situación en la que no puede existir una ruta de confianza del certificado; el cliente no confía en el certificado. Los navegadores pueden presentar una advertencia para que los usuarios puedan ignorar esto, pero no ocurre lo mismo con los clientes SSL (como la clase HttpsURLConnection o cualquier biblioteca de cliente HTTP como Apache HttpComponents Client ).

La mayoría de estas clases / bibliotecas de clientes confiarían en el almacén de confianza utilizado por la JVM para la validación de certificados. En la mayoría de los casos, este será el archivo cacerts en el directorio JRE_HOME / lib / security. Si la ubicación del almacén de confianza se ha especificado utilizando la propiedad del sistema de JVM javax.net.ssl.trustStore , entonces el almacén en esa ruta suele ser el utilizado por la biblioteca del cliente. Si tiene dudas, eche un vistazo a su clase de Merchant y descubra la clase / biblioteca que está utilizando para establecer la conexión.

Agregar el certificado del servidor que emite CA a este almacén de confianza debería resolver el problema. Puede consultar mi respuesta en una pregunta relacionada sobre cómo obtener herramientas para este propósito, pero la utilidad de keytool de Java es suficiente para este propósito.

Advertencia : el almacén de confianza es esencialmente la lista de todas las CA en las que confías. Si coloca un certificado que no pertenece a una CA en la que no confía, entonces las conexiones SSL / TLS a sitios que tienen certificados emitidos por esa entidad se pueden descifrar si la clave privada está disponible.

Actualización n. ° 2: comprensión del resultado del rastreo JSSE

El almacén de claves y los almacenes de confianza usados ​​por la JVM generalmente se enumeran al principio, algo así como los siguientes:

keyStore is : keyStore type is : jks keyStore provider is : init keystore init keymanager of type SunX509 trustStore is: C:/Java/jdk1.6.0_21/jre/lib/security/cacerts trustStore type is : jks trustStore provider is :

Si se usa el almacén de confianza incorrecto, entonces deberá volver a importar el certificado del servidor al correcto, o reconfigure el servidor para usar el que figura en la lista (no se recomienda si tiene varias JVM, y todas se usan para diferentes necesariamente).

Si desea verificar si la lista de certificados de confianza contiene los certificados requeridos, entonces hay una sección para los mismos, que comienza como:

adding as trusted cert: Subject: CN=blah, O=blah, C=blah Issuer: CN=biggerblah, O=biggerblah, C=biggerblah Algorithm: RSA; Serial number: yadda Valid from SomeDate until SomeDate

Tendrá que buscar si la CA del servidor es un tema.

El proceso de handshake tendrá algunas entradas destacadas (necesitará conocer SSL para entenderlas en detalle, pero para depurar el problema actual, bastará con saber que una falla de handshake generalmente se informa en ServerHello).

1. ClientHello

Se informará una serie de entradas cuando se inicialice la conexión. El primer mensaje enviado por el cliente en una configuración de conexión SSL / TLS es el mensaje ClientHello, generalmente se informa en los registros como:

*** ClientHello, TLSv1 RandomCookie: GMT: 1291302508 bytes = { some byte array } Session ID: {} Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA] Compression Methods: { 0 } ***

Tenga en cuenta las suites de cifrado utilizadas. Esto podría tener que estar de acuerdo con la entrada en su archivo merchant.properties, ya que la misma convención podría ser empleada por la biblioteca del banco. Si la convención utilizada es diferente, no hay motivo de preocupación, ya que ServerHello lo indicará si el paquete de cifrado no es compatible.

2. ServerHello

El servidor responde con un ServerHello, que indicará si la configuración de la conexión puede continuar. Las entradas en los registros generalmente son del siguiente tipo:

*** ServerHello, TLSv1 RandomCookie: GMT: 1291302499 bytes = { some byte array} Cipher Suite: SSL_RSA_WITH_RC4_128_SHA Compression Method: 0 ***

Tenga en cuenta la suite de cifrado que ha elegido; esta es la mejor suite disponible tanto para el servidor como para el cliente. Por lo general, el conjunto de cifrado no se especifica si hay un error. El servidor envía el certificado del servidor (y opcionalmente de toda la cadena) y se encuentra en las entradas como:

*** Certificate chain chain [0] = [ [ Version: V3 Subject: CN=server, O=server''s org, L=server''s location, ST =Server''s state, C=Server''s country Signature Algorithm: SHA1withRSA, OID = some identifer .... the rest of the certificate ***

Si la verificación del certificado ha tenido éxito, encontrará una entrada similar a:

Found trusted certificate: [ [ Version: V1 Subject: OU=Server''s CA, O="Server''s CA''s company name", C=CA''s country Signature Algorithm: SHA1withRSA, OID = some identifier

Uno de los pasos anteriores no habría tenido éxito, lo que daría como resultado el apretón de manos, ya que el apretón de manos normalmente se completa en esta etapa (en realidad, pero las etapas siguientes del apretón de manos generalmente no causan un apretón de manos). Tendrá que averiguar qué paso ha fallado y publicar el mensaje apropiado como una actualización de la pregunta (a menos que ya haya entendido el mensaje y sepa qué hacer para resolverlo).


La falla del protocolo de enlace podría ser una implementación de protocolo TLSv1 defectuosa.

En nuestro caso, esto ayudó con java 7:

java -Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1

El jvm negociará en este orden. Los servidores con la última actualización harán 1.2, los errores bajarán a v1 y eso funciona con v1 similar en java 7.


La instalación de Java Cryptography Extension (JCE) Unlimited Strength ( para JDK7 | para JDK8 ) solucionará este error. Descomprime el archivo y sigue el archivo Léame para instalarlo.


No creo que esto resuelva el problema al primer interlocutor, pero para los googlers que vienen aquí para obtener respuestas:

En la actualización 51, Java 1.8 prohíbe [1] RC4 por defecto, como podemos ver en la página Notas de la versión:

Corrección de errores: prohíbe las series de cifrado RC4

RC4 ahora se considera como un cifrado comprometido.

Los conjuntos de cifrado RC4 se han eliminado de la lista de conjuntos de cifrado activados por defecto del cliente y del servidor en la implementación Oracle JSSE. Estas suites de cifrado aún se pueden habilitar mediante los SSLEngine.setEnabledCipherSuites() y SSLSocket.setEnabledCipherSuites() . Ver JDK-8077109 (no es público).

Si su servidor tiene una fuerte preferencia por este cifrado (o usa solo este cifrado), esto puede desencadenar un handshake_failure de toma de handshake_failure en java.

Puede probar la conexión al servidor habilitando las cifras RC4 (primero, intente sin el argumento enabled para ver si desencadena un handshake_failure , luego configure enabled :

import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import java.io.*; import java.util.Arrays; /** Establish a SSL connection to a host and port, writes a byte and * prints the response. See * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services */ public class SSLRC4Poke { public static void main(String[] args) { String[] cyphers; if (args.length < 2) { System.out.println("Usage: "+SSLRC4Poke.class.getName()+" <host> <port> enable"); System.exit(1); } try { SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1])); cyphers = sslsocketfactory.getSupportedCipherSuites(); if (args.length ==3){ sslsocket.setEnabledCipherSuites(new String[]{ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "SSL_DH_anon_WITH_RC4_128_MD5", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "TLS_ECDH_RSA_WITH_RC4_128_SHA", "TLS_ECDH_anon_WITH_RC4_128_SHA", "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", "TLS_KRB5_WITH_RC4_128_MD5", "TLS_KRB5_WITH_RC4_128_SHA" }); } InputStream in = sslsocket.getInputStream(); OutputStream out = sslsocket.getOutputStream(); // Write a test byte to get a reaction :) out.write(1); while (in.available() > 0) { System.out.print(in.read()); } System.out.println("Successfully connected"); } catch (Exception exception) { exception.printStackTrace(); } } }

1 - https://www.java.com/en/download/faq/release_changes.xml


Suponiendo que está utilizando los protocolos SSL / TLS adecuados, configuró correctamente su keyStore y trustStore , y confirmó que no existe ningún problema con los certificados en sí, es posible que necesite fortalecer sus algoritmos de seguridad .

Como se mencionó en la respuesta de Vineet , una posible razón por la que recibe este error se debe a que se están utilizando conjuntos de cifrado incompatibles. Al actualizar mis local_policy y US_export_policy en la carpeta de security mi JDK con las proporcionadas en Java Cryptography Extension (JCE) , pude completar el saludo con éxito.


Tengo este error mientras trataba de usar JDK 1.7. Cuando actualicé mi JDK a jdk1.8.0_66, todo comenzó a funcionar bien.

Así que la solución más simple para este problema podría ser: actualice su JDK y podría comenzar a funcionar bien.


Tuve un problema similar; actualizar a Apache HTTPClient 4.5.3 lo solucionó.


Descargo de responsabilidad: no estoy al tanto de si la respuesta será útil para muchas personas, simplemente compartir porque podría ser.

Recibí este error al usar Parasoft SOATest para enviar XML de solicitud (SOAP).

El problema era que había seleccionado el alias incorrecto del menú desplegable después de agregar el certificado y autenticarlo.