PQC Status
Guia

TLS pós-quântico em Java: onde o JDK está e o que fazer agora

O JDK traz primitivas ML-KEM, mas o suporte a grupos TLS híbridos depende da versão que você executa: como verificar, o que mudar e como provar que funciona.

· 9 min

O Java oferece blocos de construção pós-quânticos antes de oferecer um handshake TLS pós-quântico. Para uma aplicação Java no servidor atrás de um proxy reverso, o caminho mais rápido para a troca de chaves híbrida com ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism, padronizado como NIST FIPS 203) é atualizar o proxy, não a JVM. Quando o Java atua como cliente TLS, a troca de chaves híbrida depende da versão do JDK e do provedor JSSE em uso; por isso, a única resposta confiável vem das notas de versão do build que você realmente implanta, confirmada por um teste de handshake.

Primeiro, defina de qual lado do handshake você é responsável

Uma troca de chaves TLS é negociada pelas duas pilhas que realizam o handshake, não pelo código da aplicação. Três casos cobrem quase todas as implantações Java, e cada um tem uma resposta diferente.

Priorize o trabalho com base no risco de coleta agora, decifração depois (harvest now, decrypt later, HNDL): um atacante que grava o tráfego hoje e o decifra anos depois é neutralizado pela troca de chaves, não pelo certificado. É por isso que o estabelecimento de chaves com ML-KEM vem primeiro e a migração de assinaturas pode vir depois. O registro TLS da IANA lista os grupos híbridos em uso, incluindo X25519MLKEM768 (codepoint 0x11EC), SecP256r1MLKEM768 e SecP384r1MLKEM1024 (IANA TLS parameters), e a RFC 10024 especifica o acordo de chaves híbrido pós-quântico e tradicional para TLS 1.3 (RFC 10024).

Onde o JDK está hoje

É preciso separar duas camadas: as primitivas criptográficas expostas pela Java Cryptography Architecture (JCA) e o suporte a grupos híbridos dentro da JSSE.

Primitivas: disponíveis nas versões atuais

A JEP 452 adicionou uma API de Key Encapsulation Mechanism (KEM), javax.crypto.KEM, no JDK 21. O JDK 24 adicionou implementações de ML-KEM (JEP 496) e de ML-DSA (Module-Lattice-Based Digital Signature Algorithm, NIST FIPS 204) na JEP 497, acessíveis pelas APIs habituais KeyPairGenerator, KEM e Signature, com nomes de algoritmo para cada conjunto de parâmetros. Como os recursos do JDK são mantidos nas versões seguintes, as versões posteriores os incluem. É disso que você precisa para seus próprios protocolos, encapsulamento de chaves, formatos de token e ambientes de teste. Isso, por si só, não é TLS.

Grupos TLS híbridos: leia as notas de versão do seu JDK

Oferecer um grupo híbrido em um handshake TLS 1.3 é um trabalho separado dentro da JSSE: o grupo precisa ser registrado, os key shares precisam ser gerados e interpretados, e o segredo compartilhado precisa ser derivado dos dois componentes. Se o JDK que você executa faz isso, com quais nomes de grupo e se o recurso vem habilitado por padrão, são pontos que variam conforme a versão e o build do fornecedor, já que as distribuições fazem backports seletivos. Não deduza o suporte TLS a partir da presença do ML-KEM na JCA, e não se baseie em um artigo escrito sobre outro build. Consulte as notas de versão da sua versão exata do JDK e depois verifique empiricamente com o teste de handshake abaixo.

CamadaO que verificarOnde procurar
Primitivas JCAGeração de pares de chaves ML-KEM e ML-DSA, encapsulamento, verificação de assinaturaNotas de versão do JDK, documentação dos nomes de algoritmo padrão
Grupos híbridos JSSESe o grupo híbrido aparece no ClientHello ou no ServerHelloNotas de versão do JDK, além de um handshake real com log de depuração
TLS nativo por trás de um conectorVersão da biblioteca nativa usada pelo conector (os grupos ML-KEM exigem OpenSSL 3.5 ou posterior em builds OpenSSL)Árvore de dependências, versão da biblioteca nativa em tempo de execução
Proxy ou ingressLista e ordem dos grupos, fallback clássico ainda presenteConfiguração do proxy e as notas de versão dele

Suas opções, em ordem de esforço

Terminar o TLS de entrada em um proxy

Esse é o padrão pragmático para Java no servidor. O proxy precisa de uma biblioteca TLS que implemente os grupos ML-KEM: em builds OpenSSL, isso significa OpenSSL 3.5 ou posterior. Configure o grupo híbrido em primeiro lugar e mantenha os grupos clássicos depois dele, para que clientes sem suporte híbrido continuem se conectando, e valide em homologação antes da produção. As diretivas passo a passo para os servidores mais comuns estão no nosso guia para habilitar ML-KEM no nginx, Apache, HAProxy e Caddy. Uma ressalva prática: um key share híbrido é bem maior que um key share X25519, o que pode fazer o ClientHello ultrapassar os limites de um pacote. Middleboxes antigos e equipamentos de rede com comportamento inadequado às vezes lidam mal com isso, então teste a partir das redes que seus clientes realmente usam.

Atualizar o JDK onde a JVM termina o TLS

Se um listener Java atende clientes diretamente, ou se o Java é o cliente em uma conexão que importa para você, a correção limpa é executar uma versão do JDK cuja JSSE ofereça o grupo híbrido e depois confirmar isso no tráfego real. A JSSE expõe a propriedade de sistema documentada jdk.tls.namedGroups para restringir e ordenar os grupos que oferece. Os nomes aceitos dependem da versão, então copie-os das suas notas de versão e não de um exemplo, e sempre mantenha na lista um grupo clássico como X25519. Não fixe um único grupo pós-quântico em produção.

Adicionar uma biblioteca provedora ou rotear o tráfego de saída por um gateway

Um provedor JCA ou JSSE de terceiros pode fornecer algoritmos e, em alguns casos, uma pilha TLS independente do JDK. Avalie com cuidado: instalar um provedor altera o comportamento de segurança de toda a JVM, interage com o modo FIPS e com a validação do caminho de certificação, e se torna uma dependência que você precisa manter atualizada. Quando a biblioteca permitir, restrinja a mudança ao SSLContext do cliente específico, em vez de reordenar os provedores globais. Para chamadas de saída a partir de JVMs legadas que não podem ser atualizadas, um proxy de saída que realiza o handshake costuma ser mais simples e mais fácil de auditar do que modificar cada aplicação. Observe também que conectores que usam uma biblioteca TLS nativa (por exemplo, Netty com netty-tcnative) seguem a versão dessa biblioteca, não a do JDK.

Inventarie o uso de criptografia em Java antes de mudar qualquer coisa

Todo cronograma oficial começa pela descoberta, e os auditores pedem o inventário antes de pedir a migração. Estes comandos somente leitura dão uma primeira visão; adapte os caminhos à estrutura do seu build.

# 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 mais do que o TLS. Aplicações Java também assinam JSON Web Tokens e asserções SAML, verificam JARs assinados, criptografam colunas de banco de dados e fixam âncoras de confiança. Anote os algoritmos de chave pública vulneráveis à computação quântica (RSA, ECDSA, EdDSA, ECDH, Diffie-Hellman em corpo finito e DSA são todos afetados pelo algoritmo de Shor, qualquer que seja o tamanho da chave), onde cada um é usado, quem é o responsável e se o algoritmo pode ser configurado sem alteração de código. Uma lista de materiais criptográficos legível por máquina é uma forma prática de manter essa lista atualizada: veja o que é um CBOM e como produzi-lo. Fique atento também aos arquivos de política de segurança do JDK, pois jdk.tls.disabledAlgorithms e jdk.certpath.disabledAlgorithms em java.security já determinam o que suas JVMs aceitam.

Teste o que o handshake realmente negocia

Alegações de suporte não valem nada sem um grupo negociado. Execute três verificações, nesta ordem.

# 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"

A etapa 3 é a decisiva para o Java como cliente: a saída de depuração mostra os grupos no ClientHello e o grupo escolhido para a troca de chaves. Se o grupo híbrido nunca aparece, o build do JDK não o oferece, independentemente do que a documentação sugeria. Guarde a saída como evidência, com a string de versão do JDK e a data. Nosso scanner gratuito cobre a etapa 1 pelo lado externo, incluindo versões de TLS, cipher suites e a cadeia de certificados; o que um resultado significa e o que ele não significa está descrito na nossa página de metodologia.

Como isso aparece nas auditorias

O inventário que você acabou de montar é o artefato que a maioria dos frameworks exige, e o que segue é informação, não aconselhamento jurídico. O requisito 12.3.3 do PCI DSS v4.0.1, obrigatório desde 31 de março de 2025, exige um inventário documentado das cipher suites e dos protocolos em uso, revisado pelo menos a cada 12 meses, com uma estratégia para mudanças previstas nas vulnerabilidades criptográficas: veja nossa página sobre o requisito 12.3.3 do PCI DSS. No âmbito do DORA, o Commission Delegated Regulation (EU) 2024/1774 Art. 6 exige uma política de criptografia e de controles criptográficos com disposições para atualizar ou substituir a tecnologia criptográfica à medida que a criptoanálise evolui, e o Art. 7 exige gestão de chaves e um registro dos certificados dos ativos de TIC que suportam funções críticas ou importantes (EUR-Lex). Interpretação, não texto legal: em um parque Java, a prova prática do Art. 6 é que seus serviços conseguem trocar grupos e algoritmos por configuração e por uma atualização do JDK ou do proxy, não por uma reescrita. Quanto ao status dos algoritmos, o NIST publicou os FIPS 203, 204 e 205 como padrões finais em 13 de agosto de 2024 (FIPS 203), enquanto o NIST IR 8547, que propõe descontinuar os algoritmos de chave pública com segurança de 112 bits após 2030 e proibir os algoritmos de chave pública vulneráveis à computação quântica após 2035, continua sendo um rascunho público inicial (NIST IR 8547 ipd).

O próximo passo concreto

Escolha um serviço Java acessível externamente e analise seu domínio com o PQC Status para ver qual grupo ele negocia hoje. Se a resposta for apenas clássico e um proxy terminar o TLS, atualize esse proxy para um build com OpenSSL 3.5 ou posterior e coloque o grupo híbrido antes do X25519 em homologação. Se a JVM terminar o TLS, ou se o Java for o cliente em uma conexão que transporta segredos de longa duração, registre a versão do JDK no seu inventário, leia as notas de versão dela sobre troca de chaves híbrida e capture um log de handshake como evidência, qualquer que seja o resultado. Faça uma nova análise após cada mudança e mantenha o fallback clássico até que seus clientes não precisem mais dele.

Perguntas frequentes

O JDK oferece suporte nativo a TLS híbrido pós-quântico?

O JDK traz ML-KEM e ML-DSA como primitivas criptográficas: a JEP 452 adicionou a API de Key Encapsulation Mechanism no JDK 21, e o JDK 24 adicionou as implementações de ML-KEM (JEP 496) e ML-DSA (JEP 497). A troca de chaves híbrida dentro da pilha TLS (JSSE) é um trabalho separado, e sua disponibilidade depende da versão e do build do fornecedor que você implanta. Consulte as notas de versão da sua versão exata do JDK e depois confirme no tráfego real com um handshake de verdade, em vez de presumir.

Preciso atualizar o Java se minha aplicação fica atrás de um proxy reverso?

Não para o tráfego de entrada. O proxy realiza o handshake, então o grupo negociado com navegadores e clientes de API vem do proxy e da biblioteca TLS dele, que precisa de OpenSSL 3.5 ou posterior para os grupos ML-KEM em builds OpenSSL. Você ainda precisa olhar a JVM para as conexões de saída, em que o Java é o cliente TLS, e para qualquer listener que termine o TLS dentro da JVM.

Como verifico qual grupo de troca de chaves meu cliente Java oferece?

Inicie a aplicação com a propriedade de sistema javax.net.debug configurada para registrar o handshake e depois observe a extensão supported_groups no ClientHello e o grupo selecionado para a troca de chaves. Se nenhum grupo híbrido aparecer, esse build não oferece nenhum. Salve a saída junto com a string de versão do JDK como evidência para o seu inventário criptográfico.

Devo forçar apenas um grupo pós-quântico em uma aplicação Java?

Não. Mantenha um grupo clássico como X25519 depois do grupo híbrido para que pares sem suporte híbrido continuem se conectando, e teste qualquer mudança primeiro em homologação. A JSSE expõe a propriedade documentada jdk.tls.namedGroups para restringir e ordenar os grupos oferecidos, mas os nomes aceitos dependem da versão do JDK, então copie-os das suas notas de versão e não de um exemplo.