Parece una pregunta estándar, pero no pude encontrar instrucciones claras en ningún lado.
Tengo un código Java que intenta conectarse a un servidor con un certificado probablemente autofirmado (o caducado). El código informa el siguiente error:
[HttpMethodDirector] I/O exception (javax.net.ssl.SSLHandshakeException) caught
when processing request: sun.security.validator.ValidatorException: PKIX path
building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Según tengo entendido, tengo que usar keytool y decirle a Java que está bien permitir esta conexión.
Todas las instrucciones para solucionar este problema suponen que soy completamente competente con keytool, como
generar clave privada para el servidor e importarla al almacén de claves
¿Hay alguien que pueda publicar instrucciones detalladas?
Estoy ejecutando Unix, por lo que bash script sería lo mejor.
No estoy seguro de si es importante, pero el código se ejecuta en jboss.
Respuestas:
Aquí tiene básicamente dos opciones: agregar el certificado autofirmado a su almacén de confianza JVM o configurar su cliente para
Opción 1
Exporte el certificado desde su navegador e impórtelo en su almacén de confianza JVM (para establecer una cadena de confianza):
opcion 2
Deshabilitar validación de certificado:
Tenga en cuenta que no recomiendo la Opción # 2 en absoluto . Deshabilitar el administrador de confianza derrota algunas partes de SSL y lo hace vulnerable a los ataques de hombre en el medio. Prefiera la Opción # 1 o, mejor aún, haga que el servidor use un certificado "real" firmado por una CA reconocida.
fuente
Seguí este problema a un proveedor de certificados que no es parte de los hosts de confianza JVM predeterminados a partir de
JDK 8u74
. El proveedor es www.identrust.com , pero ese no era el dominio al que intentaba conectarme. Ese dominio había obtenido su certificado de este proveedor. Consulte ¿La cobertura de raíz cruzada confiará en la lista predeterminada en JDK / JRE? - Lea un par de entradas. Consulte también Qué navegadores y sistemas operativos admiten Let's Encrypt .Entonces, para conectarme al dominio que me interesaba, que tenía un certificado emitido
identrust.com
, hice los siguientes pasos. Básicamente, tenía que obtener elDST Root CA X3
certificado identrust.com ( ) para que JVM confiara en él. Pude hacerlo usando Apache HttpComponents 4.5 así:1: Obtenga el certificado de confianza en las Instrucciones de descarga de la cadena de certificados . Haga clic en el enlace DST Root CA X3 .
2: Guarde la cadena en un archivo llamado "DST Root CA X3.pem". Asegúrese de agregar las líneas "----- BEGIN CERTIFICATE -----" y "----- END CERTIFICATE -----" en el archivo al principio y al final.
3: Cree un archivo de almacén de claves de Java, cacerts.jks con el siguiente comando:
4: Copie el almacén de claves cacerts.jks resultante en el directorio de recursos de su aplicación java / (maven).
5: Use el siguiente código para cargar este archivo y adjuntarlo al Apache 4.5 HttpClient. Esto resolverá el problema para todos los dominios que tienen certificados emitidos por
indetrust.com
util oracle que incluye el certificado en el almacén de claves predeterminado de JRE.Cuando el proyecto se construye, los cacerts.jks se copiarán en el classpath y se cargarán desde allí. En este momento, no probé con otros sitios ssl, pero si el código anterior "encadena" en este certificado, también funcionarán, pero de nuevo, no lo sé.
Referencia: contexto SSL personalizado y ¿Cómo acepto un certificado autofirmado con una conexión HttpsURLConnection de Java?
fuente
Apache HttpClient 4.5 admite la aceptación de certificados autofirmados:
Esto construye una fábrica de sockets SSL que utilizará
TrustSelfSignedStrategy
, la registra con un administrador de conexión personalizado y luego realiza un HTTP GET utilizando ese administrador de conexión.Estoy de acuerdo con aquellos que cantan "no hagas esto en producción", sin embargo, hay casos de uso para aceptar certificados autofirmados fuera de producción; los usamos en pruebas de integración automatizadas, por lo que estamos usando SSL (como en producción) incluso cuando no se ejecuta en el hardware de producción.
fuente
En lugar de configurar la fábrica de sockets predeterminada (que es IMO es algo malo), esto solo afectará la conexión actual en lugar de cada conexión SSL que intente abrir:
fuente
checkServerTrusted
no implementa la lógica necesaria para confiar en realidad el certificado y aseguran certificados no son de confianza son rechazados. Esto podría ser una buena lectura: el código más peligroso del mundo: validar certificados SSL en software que no sea de navegador .getAcceptedIssuers()
método no se ajusta a la especificación, y esta 'solución' sigue siendo radicalmente insegura.Hay una mejor alternativa para confiar en todos los certificados:
TrustStore
cree uno que confíe específicamente en un certificado determinado y úselo para crear unoSSLContext
desde el cualSSLSocketFactory
configurar elHttpsURLConnection
. Aquí está el código completo:Alternativamente, puede cargar
KeyStore
directamente desde un archivo o recuperar el Certificado X.509 de cualquier fuente confiable.Tenga en cuenta que con este código, los certificados
cacerts
no se utilizarán. Este particularHttpsURLConnection
solo confiará en este certificado específico.fuente
Confíe en todos los certificados SSL: - Puede omitir SSL si desea realizar una prueba en el servidor de prueba. Pero no use este código para la producción.
}
Llame a esta función en la función onCreate () en Actividad o en su Clase de aplicación.
Esto se puede usar para Volley en Android.
fuente
La respuesta aceptada está bien, pero me gustaría agregar algo a esto ya que estaba usando IntelliJ en Mac y no pude hacerlo funcionar usando el
JAVA_HOME
variable de ruta.Resulta que Java Home era diferente al ejecutar la aplicación desde IntelliJ.
Para averiguar exactamente dónde está, simplemente puede hacer
System.getProperty("java.home")
lo que leen los certificados de confianza.fuente
Si 'ellos' están utilizando un certificado autofirmado, ellos deben seguir los pasos necesarios para que su servidor sea utilizable. Específicamente, eso significa proporcionarle su certificado fuera de línea de manera confiable. Así que haz que hagan eso. Luego lo importa a su almacén de confianza utilizando la herramienta de claves como se describe en la Guía de referencia de JSSE. Ni siquiera pienses en el inseguro TrustManager publicado aquí.
EDITAR Para el beneficio de los diecisiete (!) Votantes negativos, y numerosos comentaristas a continuación, que claramente no han leído lo que he escrito aquí, esto no es una jeremiad contra los certificados autofirmados. No hay nada de malo con los certificados autofirmados cuando se implementan correctamente. Pero, la forma correcta de implementarlos es que el certificado se entregue de forma segura a través de un proceso fuera de línea, en lugar de hacerlo a través del canal no autenticado que se utilizarán para autenticar. ¿Seguramente esto es obvio? Ciertamente es obvio para todas las organizaciones conscientes de la seguridad para las que he trabajado, desde bancos con miles de sucursales hasta mis propias empresas. La 'solución' basada en el código del lado del cliente de confiar en todosLos certificados, incluidos los certificados autofirmados firmados por absolutamente cualquier persona o cualquier organismo arbitrario que se establezca como CA, ipso facto no es seguro. Es solo jugar a la seguridad. No tiene sentido. Está teniendo una conversación privada, a prueba de manipulaciones, a prueba de respuestas, a prueba de inyecciones con ... alguien. Cualquiera. Un hombre en el medio. Un imitador Cualquiera. También puede usar texto sin formato.
fuente
Esta no es una solución al problema completo, pero Oracle tiene una buena documentación detallada sobre cómo usar esta herramienta clave. Esto explica cómo
https://docs.oracle.com/cd/E54932_01/doc.705/e54936/cssg_create_ssl_cert.htm#CSVSG178
fuente
En lugar de usar keytool como lo sugiere el comentario principal, en RHEL puede usar update-ca-trust a partir de las versiones más recientes de RHEL 6. Deberá tener el certificado en formato pem. Luego
Edite /etc/pki/ca-trust/source/cert.p11-kit y cambie "categoría de certificado: otra entrada" a "categoría de certificado: autoridad". (O use sed para hacer esto en un script). Luego, haga
Un par de advertencias:
update-ca-trust enable
. Esto reemplazará / etc / pki / java / cacerts con un enlace simbólico que apunta a / etc / pki / ca-trust / extraído / java / cacerts. (Por lo tanto, es posible que desee hacer una copia de seguridad del primero primero).fuente
Tuve el problema de que estaba pasando una URL a una biblioteca que estaba llamando
url.openConnection();
Adapte la respuesta de jon-daniel,Con esta clase, es posible crear una nueva URL con:
Esto tiene la ventaja de que está localizado y no reemplaza el valor predeterminado
URL.openConnection
.fuente