Estoy desarrollando una aplicación Java que consulta una API REST en un servidor remoto a través de HTTP. Por razones de seguridad, esta comunicación debe cambiarse a HTTPS.
Ahora que Let's Encrypt comenzó su versión beta pública, me gustaría saber si Java funciona actualmente (o se confirma que funcionará en el futuro) con sus certificados de forma predeterminada.
Let's Encrypt consiguió su firma cruzada intermedia por IdenTrust , lo que debería ser una buena noticia. Sin embargo, no puedo encontrar ninguno de estos dos en la salida de este comando:
keytool -keystore "..\lib\security\cacerts" -storepass changeit -list
Sé que las CA de confianza se pueden agregar manualmente en cada máquina, pero dado que mi aplicación debería poder descargarse y ejecutarse sin ninguna configuración adicional, estoy buscando soluciones que funcionen "fuera de la caja". ¿Tienes buenas noticias para mí?
Respuestas:
[ Actualización 2016-06-08 : De acuerdo con https://bugs.openjdk.java.net/browse/JDK-8154757, IdenTrust CA se incluirá en Oracle Java 8u101.]
[ Actualización 2016-08-05 : Java 8u101 ha sido lanzado y de hecho incluye IdenTrust CA: notas de la versión ]
Si. El certificado Let's Encrypt es solo un certificado de clave pública normal. Java lo admite (según Let's Encrypt Certificate Compatibility , para Java 7> = 7u111 y Java 8> = 8u101).
No / depende de la JVM. El almacén de confianza de Oracle JDK / JRE hasta 8u66 no contiene el Let's Encrypt CA específicamente ni el IdenTrust CA que lo firmaron.
new URL("https://letsencrypt.org/").openConnection().connect();
por ejemplo resultados enjavax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
.Sin embargo, puede proporcionar su propio validador / definir un almacén de claves personalizado que contenga la CA raíz requerida o importar el certificado al almacén de confianza JVM.
https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 también discute el tema.
Aquí hay un código de ejemplo que muestra cómo agregar un certificado al almacén de confianza predeterminado en tiempo de ejecución. Solo necesitará agregar el certificado (exportado desde Firefox como .der y puesto en classpath)
Basado en ¿Cómo puedo obtener una lista de certificados raíz de confianza en Java? y http://developer.android.com/training/articles/security-ssl.html#UnknownCa
fuente
isrgrootx1.der
ylets-encrypt-x1-cross-signed.der
, pero ninguno de ellos parece ser el correcto.https://helloworld.letsencrypt.org
por ejemplo e inspeccione la cadena de certificados en el navegador (haciendo clic en el icono verde). Para este necesita el certificado específico del sitio, el X1 intermedio (con signo cruzado por IdenTrust) o el DSTRootCAX3. ElISRG Root X1
no funciona para el sitio helloworld porque no está en la cadena, esa es la cadena alternativa. Usaría el DSTRoot uno, simplemente exportado a través del navegador porque no lo he visto para descargar en ningún lado.javax.net.ssl.trustStore
propiedad del sistema, sino -1 para luego establecer el valor predeterminado de la JVMSSLContext
. Sería mejor crear uno nuevoSSLSocketFactory
y luego usarlo para varias conexiones (por ejemploHttpUrlConnection
) en lugar de reemplazar la configuración SSL de toda la VM. (Me doy cuenta de este cambio sólo es eficaz para la JVM en ejecución y no persisten o afectan a otros programas simplemente creo que es una mejor práctica de programación a ser explícito acerca de dónde se aplica la configuración..)Sé que el OP solicitó una solución sin cambios de configuración local, pero en caso de que desee agregar la cadena de confianza al almacén de claves de forma permanente:
fuente: https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/13
fuente
Respuesta detallada para aquellos de nosotros que estamos dispuestos a hacer cambios de configuración local que incluyen hacer una copia de seguridad del archivo de configuración:
1. Pruebe si está funcionando antes de los cambios
Si aún no tiene un programa de prueba, puede usar mi programa de ping SSLPing de Java que prueba el protocolo de enlace TLS (funcionará con cualquier puerto SSL / TLS, no solo HTTPS). Usaré SSLPing.jar preconstruido, pero leer el código y construirlo usted mismo es una tarea rápida y fácil:
Dado que mi versión de Java es anterior a la 1.8.0_101 (no publicada al momento de escribir esto), un certificado Let's Encrypt no se verificará de manera predeterminada. Veamos cómo se ve la falla antes de aplicar la corrección:
2. Importar el certificado
Estoy en Mac OS X con el conjunto de variables de entorno JAVA_HOME. Los comandos posteriores supondrán que esta variable está establecida para la instalación de Java que está modificando:
Haga una copia de seguridad del archivo cacerts que modificaremos para que pueda hacer una copia de seguridad de cualquier cambio sin reinstalar el JDK:
Descargue el certificado de firma que necesitamos importar:
Realizar la importación:
3. Verifique que esté funcionando después de los cambios
Verifique que Java ahora esté contento de conectarse al puerto SSL:
fuente
Para los JDK que aún no admiten los certificados Let's Encrypt, puede agregarlos al JDK
cacerts
siguiendo este proceso (gracias a esto ).Descargue todos los certificados en https://letsencrypt.org/certificates/ (elija el formato der ) y agréguelos uno por uno con este tipo de comando (ejemplo para
letsencryptauthorityx1.der
):fuente