¿Cómo generar nuevos parámetros Diffie-Hellman de 2048 bits con Java keytool?

9

Somos no expertos que intentamos, sin éxito hasta ahora, actualizar la configuración de nuestro servidor web (JBoss-5.1.0.GA) para cumplir con los estándares de Diffie-Hellman. Después de ejecutar una prueba en https://weakdh.org/sysadmin.html , se nos dice que necesitamos "generar nuevos parámetros Diffie-Hellman de 2048 bits". En el pasado, hemos generado claves con la herramienta de claves Java, pero no hemos podido encontrar ninguna información sobre la generación de un nuevo parámetro Diffie-Hellman de 2048 bits con la herramienta de claves Java. ¿Alguien sabe cómo hacer esto o podría señalarnos en la dirección correcta? ¡Gracias!

usuario2072931
fuente

Respuestas:

13

No puedes hacer eso con keytool. Primero, keytoolno es compatible con DH en absoluto. En segundo lugar, keytoolno genera parámetros por sí mismos para ningún algoritmo, solo una clave privada / par de claves. En tercer lugar, cuando keytoolgenera un par de claves, también genera un certificado autofirmado (que a veces se reemplaza posteriormente por un certificado "real" emitido por CA) y es imposible generar un certificado autofirmado para DH porque DH no firma. Usted podría escribir una (aproximadamente 10 líneas) muy simple programa Java para generar parámetros de DH. Pero probablemente no te haría ningún bien porque:

Java no acepta los parámetros DHE aquí de todos modos. JbossWS (el servidor web Jboss, más tarde Wildfly) es una bifurcación de Tomcat, y normalmente utiliza la implementación Java de SSL / TLS, JSSE. Hasta Java 7, JSSE usa sus propios parámetros DHE que son de 768 bits, lo cual es inaceptablemente débil. (Excepto para las suites EXPORT donde JSSE obedece el requisito de RFC para DH-512, que está totalmente roto, pero las suites EXPORT están, por diseño, totalmente rotas de todos modos, y están deshabilitadas por defecto en Java 7 en adelante.) Java 8 JSSE le permite controla el tamaño de los parámetros DHE, pero no el valor real.

Sus opciones (algunas superpuestas) son:

Use Java 8. JSSE en Java 8, pero no antes, el valor predeterminado es DHE a 1024 bits, que la mayoría de las autoridades consideran lo suficientemente fuerte, aunque débildh.org no lo hace, y le permite especificar más, consulte https://docs.oracle.com /javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#customizing_dh_keys y para antecedentes /programming/30352105/how-to-set-custom-dh-group-in-java -sslengine-to-prevent-logjam-attack . Tenga en cuenta que si tiene clientes Java anteriores a Java 8, fallarán si el servidor usa DHE de más de 1024 bits. No conozco ningún otro cliente que tenga este problema, pero pruebe el suyo antes de comprometerse con este cambio.

Habilitar ECDHE. JSSE en Java 7 y posterior implementa ECDHE, que no está sujeto a una precomputación como DHE, (normalmente) usando P-256, que es lo suficientemente fuerte. (Aunque algunas personas no confían en ninguna de las curvas NIST ECC porque NIST en general está influenciado por NSA, aunque ninguna fuente abierta que conozco ha mostrado un problema específicamente en las curvas ECC). Java 6 en realidad tiene la parte JSSE para ECDHE pero solo está habilitado si la JVM tiene un "proveedor" criptográfico para primitivas ECC, que Java 6 no tiene. bcprov - * - jdk15on de http://www.bouncycastle.org/ es un proveedor de JCE para una variedad de primitivas criptográficas Java, incluido ECC, por lo que si agrega el jar a su JRE/lib/exty agrega org.bouncycastle.jce.provider.BouncyCastleProvidera la lista JRE/lib/security/java.security(o haga unSecurity.add/insertProvider()en algún lugar temprano en su código) Java 6 puede hacer ECDHE. Por supuesto, si debe tener Java 6 todavía en uso, es una pregunta en sí mismo.

Hace unos años, el soporte para ECDHE en los navegadores y otros clientes era dudoso, pero hoy AFAIK todos los navegadores actualizados lo admiten y lo prefieren a DHE, es decir, el navegador hola enumera las suites ECDHE antes que las suites DHE, por lo que que si el servidor implementa ambos debe elegir ECDHE. Los clientes que no son del navegador tal vez no; prueba para estar seguro.

Deshabilitar DHE. Puede configurar la lista de cifrados en el atributo Conector para excluir los cifrados DHE; mientras lo hace, también excluye staticDH y staticECDH que son inútiles, y (solo) DES y (todos) "EXPORTAR" si están presentes (Java 6). Esto significa que los navegadores y los clientes que no hacen ECHDE se quedarán con RSA simple y sin secreto de reenvío, pero al menos tienen secreto "actual". No recuerdo con certeza, pero creo que la configuración del conector 5.1 todavía estaba en algún lugar $server/deploy/jbossweb/server.xml.

Prueba nativo. Tomcat, que como dije JbossWS comenzó, tiene una opción para implementar HTTPS (SSL / TLS) usando "nativo", también conocido como "APR", que en realidad es OpenSSL en lugar de JSSE. He tenido un éxito mixto al hacer que esta opción funcione en JbossWS, y no recuerdo sobre 5.1. Si su JbossWS tiene una opción nativa de TC viable, y si puede manejar la configuración de parámetros DH, use openssl para generar los parámetros DH y las instrucciones nativas de JbossWS para configurarlos.

dave_thompson_085
fuente
Gracias por esta gran información. La respuesta para nosotros finalmente no involucró keytool, solo cambios en nuestro archivo server.xml, pero voy a verificar esta respuesta.
user2072931
4

En realidad, puede especificar parámetros DHE personalizados con versiones recientes de Java 8 . Eso es independiente de la aplicación (siempre que use la implementación JSSE TLS).

Primero debe especificar el tamaño de la clave DHE para usar ( -Djdk.tls.ephemeralDHKeySize=1024o -Djdk.tls.ephemeralDHKeySize=2048). En el servidor, esto utilizará una combinación predefinida de generador / cebado para DHE. Con Java 8 solo se puede usar 1024 o 2048, JDK 9 admitirá tamaños más grandes .

Si desea proporcionar una combinación diferente, puede especificarlas en jre / lib / security / Java.security con la jdk.tls.server.defaultDHEParameterspropiedad de seguridad (desde 8u51). Toma una lista de parámetros (uno para cada tamaño de clave utilizado) y debe contener el primo y el generador (generalmente 2 o 5) como hexadecimal.

Si solía openssl dhparam -out dhparam2048.pem 2048generar un nuevo par, puede usarlo openssl dhparam -noout -text -check -in dhparam2048.pempara leer e imprimir ese archivo en modo de texto. Deberá copiar y pegar el texto en las propiedades de seguridad de Java ( tr -d ':'para eliminar la :representación hexadecimal openssl)

Aquí hay una muestra (solo 1024 bis):

>openssl dhparam -in p -check -text -noout | tr -d ':'
PKCS#3 DH Parameters: (1024 bit)
    prime:
       00f7a63b59edcc43a43df12077f0e9
        14129c20a73cef95f919896e608ebc
        8722776c948765bbbf61542e118329
        6c6ea74ecbded3a93aff77a062aba4
        fcf04fc01030e65077f5a802605058
        65b836368dd5ea389d77691fac0f2c
        f7a161c51c8e97ddecb3cf7f872b0c
        cfaf54373d5203edcabc575e871bb1
        107ec2f30c78ebf403
    generator: 2 (0x2)
DH parameters appear to be ok.

Y esto da como resultado

jdk.tls.server.defaultDHEParameters= \
    { \
        00f7a63b59edcc43a43df12077f0e9 \
        14129c20a73cef95f919896e608ebc \
        8722776c948765bbbf61542e118329 \
        6c6ea74ecbded3a93aff77a062aba4 \
        fcf04fc01030e65077f5a802605058 \
        65b836368dd5ea389d77691fac0f2c \
        f7a161c51c8e97ddecb3cf7f872b0c \
        cfaf54373d5203edcabc575e871bb1 \
        107ec2f30c78ebf403, 2 }

Debe reiniciar el Servidor y verificar que realmente utiliza este primer (y no los predeterminados) ya que el proceso no es sencillo, por lo que muchas cosas pueden salir mal. El valor predeterminado se define en la fuente , para 2048 bits el primo es del borrador TLS FFDHE.

Por ejemplo, cuando ejecuto openssl s_client, puedo ver 1024bit prime ( ffffff ffffffffc90f ... 5381ffffffffffffffff ) al conectarme a un servidor Java 8 JSSE:

>openssl s_client -msg -cipher DHE-RSA-AES128-SHA256 -connect localhost:1234
...
<<< TLS 1.2 Handshake [length 018f], ServerKeyExchange
0c 00 01 8b 00 80 ff ff ff ff ff ff ff ff c9 0f
da a2 21 68 c2 34 c4 c6 62 8b 80 dc 1c d1 29 02
4e 08 8a 67 cc 74 02 0b be a6 3b 13 9b 22 51 4a
08 79 8e 34 04 dd ef 95 19 b3 cd 3a 43 1b 30 2b
0a 6d f2 5f 14 37 4f e1 35 6d 6d 51 c2 45 e4 85
b5 76 62 5e 7e c6 f4 4c 42 e9 a6 37 ed 6b 0b ff
5c b6 f4 06 b7 ed ee 38 6b fb 5a 89 9f a5 ae 9f
24 11 7c 4b 1f e6 49 28 66 51 ec e6 53 81 ff ff
ff ff ff ff ff ff 00 01 02 ...

En lugar de esto, debe ver sus parámetros personalizados cuando esté instalado.

Los parámetros predeterminados para Java 7 (768 bits) serían "e9e642 ... 7a3daf" con un generador largo "30470ad..529252" como se define en ParameterCache .

Eckes
fuente
3

He pasado por este mismo problema, pero de Glassfish.

En primer lugar, recomendaría (si puede) colocar algún tipo de proxy inverso frente a su servidor JBoss, ya que eliminará el enlace entre la seguridad de cifrado / certificado y la versión de Java que está ejecutando.

Para obtener una longitud de clave DH efímera mayor de 768 bits, debe estar ejecutándose en Java 8. 1024 es el nuevo valor predeterminado, y puede ir hasta 2048 utilizando jdk.tls.ephemeralDHKeySize(detalles: personalización de claves DH ). Por lo que pude encontrar, no existe el concepto de regenerar los parámetros clave por separado en Java.

David Hutchison
fuente
Gracias por esta sugerencia de una alternativa. Podemos analizar esto en el futuro.
user2072931
Ahora hay, vea serverfault.com/a/798036/4591
eckes el
para glassfish / payara / payara-micro para deshabilitar los cifrados DHE agregue <ssl tls-enabled="false" classname="com.sun.enterprise.security.ssl.GlassfishSSLImpl" tls11-enabled="false" cert-nickname="s1as" ssl3-tls-ciphers="+TLS_RSA_WITH_AES_256_CBC_SHA,+TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_RSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA256,+TLS_ECDH_RSA_WITH_AES_256_GCM_SHA256"></ssl>al <protocol name="http-listener-2" security-enabled="true">conector SSL
Markus