PQC Status
Guía

TLS poscuántico en Java: situación actual del JDK y qué hacer ahora

El JDK incluye primitivas ML-KEM, pero el soporte de grupos TLS híbridos depende de la versión que ejecute: cómo comprobarlo, qué cambiar y cómo demostrar que funciona.

· 9 min

Java le ofrece los componentes poscuánticos antes que un handshake TLS poscuántico. Para una aplicación Java de servidor situada detrás de un proxy inverso, la vía más rápida hacia el intercambio de claves híbrido con ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism, estandarizado como NIST FIPS 203) consiste en actualizar el proxy, no la JVM. Cuando Java actúa como cliente TLS, el intercambio de claves híbrido depende de la versión del JDK y del proveedor JSSE utilizado, por lo que la única respuesta fiable procede de las notas de versión de la compilación que realmente despliega, confirmada mediante una prueba de handshake.

Determine primero qué lado del handshake controla

El intercambio de claves TLS lo negocian las dos pilas que realizan el handshake, no el código de la aplicación. Tres casos cubren casi todos los despliegues Java, y cada uno tiene una respuesta distinta.

Priorice el trabajo según el riesgo de «recolectar ahora, descifrar después» (HNDL, harvest now, decrypt later): a un atacante que graba el tráfico hoy y lo descifra años más tarde lo frena el intercambio de claves, no el certificado. Por eso el establecimiento de claves con ML-KEM va primero y la migración de firmas puede venir después. El registro TLS de IANA recoge los grupos híbridos en uso, entre ellos X25519MLKEM768 (codepoint 0x11EC), SecP256r1MLKEM768 y SecP384r1MLKEM1024 (parámetros TLS de IANA), y RFC 10024 especifica el acuerdo de claves híbrido poscuántico y tradicional para TLS 1.3 (RFC 10024).

Situación actual del JDK

Conviene distinguir dos capas: las primitivas criptográficas expuestas a través de la Java Cryptography Architecture (JCA) y el soporte de grupos híbridos dentro de JSSE.

Primitivas: disponibles en las versiones actuales

JEP 452 añadió en JDK 21 una API de mecanismo de encapsulación de claves (KEM), javax.crypto.KEM. JDK 24 añadió implementaciones de ML-KEM (JEP 496) y de ML-DSA (Module-Lattice-Based Digital Signature Algorithm, NIST FIPS 204) en JEP 497, accesibles mediante las API habituales KeyPairGenerator, KEM y Signature con nombres de algoritmo para cada conjunto de parámetros. Como las funcionalidades del JDK se mantienen de una versión a otra, las versiones posteriores las incluyen. Esto es lo que necesita para sus propios protocolos, el envoltorio de claves, los formatos de token y los entornos de prueba. Por sí solo, no es TLS.

Grupos TLS híbridos: consulte las notas de versión de su JDK

Ofrecer un grupo híbrido en un handshake TLS 1.3 es un trabajo independiente dentro de JSSE: hay que registrar el grupo, generar y analizar los key shares y derivar el secreto compartido a partir de ambos componentes. Que el JDK que ejecuta lo haga, con qué nombres de grupo y si está activado por defecto varía según la versión y la compilación del proveedor, ya que las distribuciones aplican backports de forma selectiva. No deduzca el soporte TLS de la presencia de ML-KEM en la JCA, ni se base en un artículo escrito sobre otra compilación. Consulte las notas de versión de su versión exacta del JDK y verifíquelo después de forma empírica con la prueba de handshake que se describe más abajo.

CapaQué verificarDónde consultar
Primitivas JCAGeneración de pares de claves ML-KEM y ML-DSA, encapsulación, verificación de firmasNotas de versión del JDK, documentación de nombres de algoritmos estándar
Grupos híbridos JSSESi el grupo híbrido aparece en el ClientHello o el ServerHelloNotas de versión del JDK, junto con un handshake real con registro de depuración
TLS nativo detrás de un conectorVersión de la biblioteca nativa que usa el conector (los grupos ML-KEM requieren OpenSSL 3.5 o posterior en compilaciones basadas en OpenSSL)Árbol de dependencias, versión de la biblioteca nativa en tiempo de ejecución
Proxy o ingressLista y orden de grupos, presencia del respaldo clásicoConfiguración del proxy y sus propias notas de versión

Sus opciones, por orden de esfuerzo

Terminar el TLS entrante en un proxy

Es la opción pragmática por defecto para Java de servidor. El proxy necesita una biblioteca TLS que implemente los grupos ML-KEM: en compilaciones basadas en OpenSSL, eso significa OpenSSL 3.5 o posterior. Configure el grupo híbrido en primer lugar y mantenga los grupos clásicos detrás, para que los clientes sin soporte híbrido sigan conectándose, y valide en preproducción antes de pasar a producción. Las directivas paso a paso para los servidores habituales están en nuestra guía para activar ML-KEM en nginx, Apache, HAProxy y Caddy. Una precaución práctica: un key share híbrido es bastante más grande que un key share X25519, lo que puede hacer que el ClientHello supere los límites de un paquete. Algunos middleboxes antiguos y equipos de red con un comportamiento deficiente lo gestionan mal, así que pruebe desde las redes que sus clientes utilizan realmente.

Actualizar el JDK allí donde la JVM termina el TLS

Si un listener Java atiende directamente a los clientes, o si Java es el cliente en una conexión que le importa, la solución limpia es ejecutar una versión del JDK cuyo JSSE ofrezca el grupo híbrido y confirmarlo después en la red. JSSE expone la propiedad de sistema documentada jdk.tls.namedGroups para restringir y ordenar los grupos que ofrece. Los nombres que acepta dependen de la versión, así que tómelos de sus notas de versión en lugar de copiar un ejemplo, y deje siempre en la lista un grupo clásico como X25519. No fije un único grupo poscuántico en producción.

Añadir una biblioteca proveedora o enrutar el tráfico saliente a través de una pasarela

Un proveedor JCA o JSSE de terceros puede aportar algoritmos y, en algunos casos, una pila TLS independiente del JDK. Valórelo con cuidado: instalar un proveedor modifica el comportamiento de seguridad de toda la JVM, interactúa con el modo FIPS y con la validación de la ruta de certificación, y se convierte en una dependencia que debe mantener parcheada. Limite el cambio al SSLContext del cliente concreto cuando la biblioteca lo permita, en lugar de reordenar los proveedores globales. Para las llamadas salientes desde JVM heredadas que no pueden actualizarse, un proxy de salida que realice el handshake suele ser más sencillo y fácil de auditar que modificar cada aplicación. Tenga en cuenta también que los conectores que usan una biblioteca TLS nativa (por ejemplo, Netty con netty-tcnative) dependen de la versión de esa biblioteca, no del JDK.

Inventariar el uso criptográfico en Java antes de cambiar nada

Todos los calendarios oficiales empiezan por el descubrimiento, y los auditores piden el inventario antes que la migración. Estos comandos de solo lectura le ofrecen una primera pasada; adapte las rutas a la estructura de su proyecto.

# TLS and crypto entry points in application code
grep -rnE "SSLContext|SSLSocketFactory|HttpsURLConnection|TrustManager|KeyManagerFactory" --include="*.java" src/

# algorithm names and keystore formats hard coded in source or configuration
grep -rnE "RSA|ECDSA|SHA1|MD5|PKCS12|JKS" --include="*.java" --include="*.properties" --include="*.yml" .

# which TLS stack each service really uses
mvn -q dependency:tree | grep -Ei "netty|tcnative|conscrypt|bouncycastle|okhttp|httpclient"
./gradlew dependencies --configuration runtimeClasspath | grep -Ei "netty|tcnative|okhttp|httpclient"

# keys and certificates in a keystore, with their algorithms
keytool -list -v -keystore keystore.p12 -storetype PKCS12 | grep -E "Alias name|Signature algorithm name|Subject Public Key Algorithm"

Registre algo más que TLS. Las aplicaciones Java también firman JSON Web Tokens y aserciones SAML, verifican JAR firmados, cifran columnas de bases de datos y fijan anclas de confianza. Anote los algoritmos de clave pública vulnerables a la computación cuántica (RSA, ECDSA, EdDSA, ECDH, Diffie-Hellman de campo finito y DSA se ven todos afectados por el algoritmo de Shor, sea cual sea el tamaño de clave), dónde se utiliza cada uno, quién es su responsable y si el algoritmo puede configurarse sin modificar el código. Un inventario criptográfico legible por máquina es una forma práctica de mantener esa lista actualizada: consulte qué es un CBOM y cómo generarlo. Vigile también los archivos de política de seguridad del JDK, ya que jdk.tls.disabledAlgorithms y jdk.certpath.disabledAlgorithms en java.security ya determinan lo que sus JVM aceptarán.

Comprobar lo que el handshake negocia realmente

Las afirmaciones sobre el soporte no valen nada sin un grupo negociado. Realice tres comprobaciones, en este orden.

# 1. external view of the listener (OpenSSL 3.5 or later on the client side)
openssl s_client -connect api.example.com:443 -groups X25519MLKEM768 </dev/null 2>&1 | grep -i "Negotiated TLS1.3 group"

# 2. the classical fallback must still work
openssl s_client -connect api.example.com:443 -groups X25519 </dev/null 2>&1 | grep -i "Negotiated TLS1.3 group"

# 3. what the Java client offers, and what the peer selects
java -Djavax.net.debug=ssl:handshake -jar client.jar 2>&1 | grep -iE "supported_groups|named group|key_share"

El paso 3 es el decisivo cuando Java actúa como cliente: la salida de depuración muestra los grupos del ClientHello y el grupo elegido para el intercambio de claves. Si el grupo híbrido no aparece nunca, la compilación del JDK no lo ofrece, diga lo que diga la documentación. Conserve la salida como evidencia, junto con la cadena de versión del JDK y la fecha. Nuestro escáner gratuito cubre el paso 1 desde el exterior, incluidas las versiones de TLS, los conjuntos de cifrado y la cadena de certificados; lo que un resultado significa y lo que no se describe en nuestra página de metodología.

Cómo se refleja esto en las auditorías

El inventario que acaba de elaborar es el artefacto que piden la mayoría de los marcos, y lo que sigue es información, no asesoramiento jurídico. El requisito 12.3.3 de PCI DSS v4.0.1, obligatorio desde el 31 de marzo de 2025, exige un inventario documentado de los conjuntos de cifrado y protocolos en uso, revisado al menos cada 12 meses, con una estrategia ante los cambios previstos en las vulnerabilidades criptográficas: consulte nuestra página sobre el requisito 12.3.3 de PCI DSS. En el marco de DORA, el Art. 6 del Reglamento Delegado (UE) 2024/1774 de la Comisión exige una política de cifrado y controles criptográficos con disposiciones para actualizar o cambiar la tecnología criptográfica en función de la evolución del criptoanálisis, y el Art. 7 exige la gestión de claves y un registro de certificados para los activos de TIC que respaldan funciones críticas o importantes (EUR-Lex). Interpretación, no texto: en un parque Java, la prueba práctica del Art. 6 es que sus servicios puedan cambiar de grupos y algoritmos mediante configuración y una actualización del JDK o del proxy, no mediante una reescritura. En cuanto al estado de los algoritmos, NIST publicó FIPS 203, 204 y 205 como estándares definitivos el 13 de agosto de 2024 (FIPS 203), mientras que NIST IR 8547, que propone declarar obsoletos los algoritmos de clave pública con seguridad de 112 bits después de 2030 y prohibir los algoritmos de clave pública vulnerables a la computación cuántica después de 2035, sigue siendo un borrador público inicial (NIST IR 8547 ipd).

El siguiente paso concreto

Elija un servicio Java accesible desde el exterior y analice su dominio con PQC Status para ver qué grupo negocia hoy. Si la respuesta es solo clásico y un proxy termina el TLS, actualice ese proxy a una compilación con OpenSSL 3.5 o posterior y sitúe el grupo híbrido por delante de X25519 en preproducción. Si la JVM termina el TLS, o si Java es el cliente en una conexión que transporta secretos de larga duración, registre la versión del JDK en su inventario, consulte sus notas de versión sobre el intercambio de claves híbrido y capture en cualquier caso un registro del handshake como evidencia. Vuelva a analizar tras cada cambio y mantenga el respaldo clásico hasta que sus clientes ya no lo necesiten.

Preguntas frecuentes

¿Admite el JDK TLS híbrido poscuántico de serie?

El JDK incluye ML-KEM y ML-DSA como primitivas criptográficas: JEP 452 añadió la API de mecanismo de encapsulación de claves en JDK 21, y JDK 24 añadió implementaciones de ML-KEM (JEP 496) y ML-DSA (JEP 497). El intercambio de claves híbrido dentro de la pila TLS (JSSE) es un trabajo independiente, y su disponibilidad depende de la versión y de la compilación del proveedor que despliegue. Consulte las notas de versión de su versión exacta del JDK y confírmelo después en la red con un handshake real, en lugar de darlo por supuesto.

¿Necesito actualizar Java si mi aplicación está detrás de un proxy inverso?

No para el tráfico entrante. El proxy realiza el handshake, por lo que el grupo negociado con navegadores y clientes de API depende del proxy y de su biblioteca TLS, que requiere OpenSSL 3.5 o posterior para los grupos ML-KEM en compilaciones basadas en OpenSSL. Sigue siendo necesario revisar la JVM para las conexiones salientes, en las que Java es el cliente TLS, y para cualquier listener que termine el TLS dentro de la JVM.

¿Cómo compruebo qué grupo de intercambio de claves ofrece mi cliente Java?

Inicie la aplicación con la propiedad de sistema javax.net.debug configurada para registrar el handshake y, a continuación, examine la extensión supported_groups del ClientHello y el grupo seleccionado para el intercambio de claves. Si no aparece ningún grupo híbrido, esa compilación no lo ofrece. Guarde la salida junto con la cadena de versión del JDK como evidencia para su inventario criptográfico.

¿Debo forzar únicamente un grupo poscuántico en una aplicación Java?

No. Mantenga un grupo clásico como X25519 detrás del grupo híbrido para que los interlocutores sin soporte híbrido puedan seguir conectándose, y pruebe cualquier cambio primero en preproducción. JSSE expone la propiedad documentada jdk.tls.namedGroups para restringir y ordenar los grupos ofrecidos, pero los nombres aceptados dependen de la versión del JDK, así que tómelos de sus notas de versión y no de un ejemplo.