Skip to main content
The Java Platform and Post-Quantum Cryptography: From Threat Models to JDK Delivery
  1. Posts/

The Java Platform and Post-Quantum Cryptography: From Threat Models to JDK Delivery

·2982 words·14 mins
NeatGuyCoding
Author
NeatGuyCoding

The Java Platform and Post-Quantum Cryptography: From Threat Models to JDK Delivery
#

If a large-scale quantum computer reaches cryptographically relevant scale (Cryptographically Relevant Quantum Computer, CRQC), Shor’s algorithm can factor integers and solve discrete logarithms in polynomial time, breaking the RSA, finite-field Diffie–Hellman, and elliptic-curve systems that today’s TLS and PKI depend on. Symmetric algorithms are not directly threatened by Shor; Grover’s algorithm offers only a quadratic speedup for symmetric key search, which is why the industry often recommends AES-256 for high-value scenarios—a common risk judgment, not a JDK default mandate.

For Java server workloads, the urgent problem is often not “wait until a quantum machine ships, then change one config line,” but harvest now, decrypt later (HNDL): adversaries can archive handshakes and ciphertext today and recover session keys once a CRQC becomes available. The motivation sections of JEP 496 and JEP 527 use similar framing. By contrast, certificates and JAR signatures relate more to identity forgery and supply-chain trust, with rotation cadences different from “historical traffic confidentiality.” Prioritizing key exchange over signature upgrades is a risk-modeling view (speaker perspective); NIST and the JEPs do not prescribe a single global schedule in those words—enterprises must still plan ML-DSA signature migration in parallel.

The sections below follow threat → standard naming → platform APIs → protocol deployment → operations, aimed at engineers who already know JCA/JSSE. Each technical block tries to cover: why it matters, mechanism and constraints, minimal runnable example, and common pitfalls. JDK versions follow OpenJDK JEPs and release notes; slide mentions of ML-KEM/ML-DSA backports to JDK 21/17 (second half of 2026) were not verified in the corresponding JEP text—production schedules should track Oracle update announcements.

Architecture teams should record three columns in compliance ledgers: FIPS algorithm name, IANA TLS group name, and minimum JDK version—a mismatch in any one produces the illusion that “the crypto library is upgraded but production handshakes are still ECDHE.”


The weak link in the TLS handshake#

Why: Enterprise confidential traffic, healthcare and financial messages, and cloud API calls mostly run over TLS. A threat model that only asks “when will a CRQC be commercial?” underestimates adversaries who capture today and decrypt tomorrow—a different time scale from certificate “expire and rotate.”

Mechanism: RFC 8446 divides TLS 1.3 into key exchange, authentication (digital signatures), and record-layer symmetric encryption. The first two rely on classical asymmetric primitives; after the handshake completes, the record layer is protected by negotiated symmetric keys and is not directly threatened by Shor—but in long-retention logging scenarios, once key exchange in the handshake is broken, confidentiality of historical Application Data is lost. Authentication failures imply forged identity and man-in-the-middle risk; that attack surface should be assessed separately from HNDL against past confidentiality.

Slide: TLS 1.3 handshake segments for Key Exchange and Authentication, with Shor’s threat to asymmetric parts annotated

Figure: A CRQC Will Break Internet Communications Using Traditional Asymmetric Cryptography — TLS 1.3 handshake Key Exch and Authn depend on traditional asymmetric cryptography.

Mechanism and constraints: Shor affects public-key systems; it does not replace protection against TLS implementation flaws, weak cipher suites, or poor key management. Whether a peer negotiates a post-quantum hybrid group can be probed with OpenSSL s_client -groups (depends on peer and local OpenSSL version, not JDK behavior).

Minimal observation (JDK applications often need no code changes to benefit from hybrid groups on JDK 27; see below):

openssl s_client -connect api.example.com:443 -tls1_3 -groups X25519MLKEM768 </dev/null 2>/dev/null \
  | grep -E 'Protocol|Cipher|Named Group'

Common pitfalls: Treating “symmetric suites are still safe” as “the entire TLS path can defer migration,” while ignoring archived handshakes and ciphertext. Another pitfall is treating HNDL as the only priority and deferring ML-DSA certificates and JAR signature upgrades indefinitely—federal and industry guidance (e.g., CNSA 2.0 direction) still requires signature-system migration, with urgency varying by scenario.


NIST standards and engineering naming alignment
#

Why: Procurement contracts, penetration-test reports, and JDK release notes use different namespaces; misalignment causes failed acceptance tests or wrong selections (e.g., conflating competition-era Kyber with FIPS ML-KEM).

Mechanism: The NIST Post-Quantum Cryptography project issued a call for proposals in 2016, announced first-round selections in 2022, and published FIPS 203 ML-KEM, FIPS 204 ML-DSA, and FIPS 205 SLH-DSA in August 2024. Competition nicknames Kyber and Dilithium are not guaranteed to interoperate with early implementations—the JEP 496 text states ML-KEM and Kyber do not interoperate; JEP 497 says the same for ML-DSA and Dilithium. Falcon maps to ongoing FN-DSA work (no final FIPS 206 page yet); HQC was selected for standardization in March 2025 (NIST project page).

NIST PQC Standardization timeline: 2016 call for proposals through August 2024 FIPS 203/204/205 publication

Figure: NIST PQC Standardization — December 2016 Call for Proposals through August 2024 Final FIPS Published.

Competition / legacy nameFIPSJDK family name (examples)
Kyber203ML-KEM, ML-KEM-768
Dilithium204ML-DSA, ML-DSA-65
SPHINCS+205SLH-DSA (JDK built-in scope not expanded here)

What to do: Pin FIPS numbers in architecture decision records (ADRs) or infrastructure-as-code to avoid nickname drift:

crypto_standards:
  kem: { name: ML-KEM, fips: "203", jca: ML-KEM-768 }
  signature: { name: ML-DSA, fips: "204", jca: ML-DSA-65 }

Common pitfalls: Procurement lists “Kyber” while acceptance scripts call ML-KEM parameter sets—interop fails and gets blamed on a JDK bug. Another pitfall is assuming FIPS 206 (FN-DSA) is already published—as of common verification paths, a final page may still be unavailable; write “standardization in progress.”


Hybrid schemes: the security narrative for transition
#

Why: Pure post-quantum algorithms are still under ongoing cryptanalysis; pure classical algorithms cannot resist HNDL under a CRQC. Hybrids are an engineering compromise between known risks and caution toward newer algorithms.

Mechanism: The transition period widely uses classical + post-quantum combinations: as long as one side of the combination remains unbroken within a foreseeable horizon, hybrid key exchange can sustain a “defensible” security claim. JEP 527 states: secure as long as one of the algorithms remains unbroken. NIST FIPS cover single-algorithm semantics; TLS named group combinations are defined by the IETF (e.g., draft-ietf-tls-hybrid-design); IANA TLS Supported Groups already registers entries such as X25519MLKEM768.

Mermaid diagram 1

What to do: Product ADRs can document a default preference for X25519MLKEM768, aligned with JDK 27 default policy; compliance narratives should note “NIST FIPS cover single algorithms; TLS combinations are IETF-defined,” avoiding audit requests for NIST “hybrid suite certificates”—such combinations are typically outside single-algorithm FIPS certification scope.

Common pitfalls: Assuming “ML-KEM-768 tested in the lab” means production TLS already negotiates hybrid groups—when JEP 496 delivered ML-KEM APIs in JDK 24, Non-Goals explicitly state ML-KEM TLS in javax.net.ssl was not yet supported—PQ hybrid TLS arrives in JDK 27 (JEP 527). Treating “default hybrid” as change-management-free: IETF drafts may still adjust wire formats; reserve regression windows.


JCA layering and roadmap gates
#

Why: Java has long abstracted hardware and FIPS modules through providers; PQC follows the same model, or HSMs, cloud KMS, and SunJCE would diverge.

Mechanism: Applications program against JCA engine classes such as Signature, KeyPairGenerator, and Cipher, implemented by Providers (SunJCE, third-party HSM). KEM was added from JDK 21; KDF finalized in JDK 25 (previewed in JDK 24 via JEP 478). Weak-algorithm deprecation follows the Oracle Java Cryptographic Roadmap (the page updates over time; CI should bind to specific JDK version release notes).

Building the PQC Foundation: Application maps through JCA/JCE to ML-KEM, ML-DSA, HKDF, HPKE

Figure: Building the PQC Foundation — KEM and KDF marked New in JCA/JCE, corresponding to ML-KEM, HKDF, and related implementations.

What to do: Upgrade pipelines should run three checks in parallel—(1) whether java.security disabled algorithms match the roadmap; (2) whether standard algorithm names include ML-KEM/ML-DSA; (3) if using third-party providers such as Bouncy Castle, whether their PQ implementations match SunJCE parameter sets.

Common pitfalls: Watching only the JDK major version while ignoring java.security properties and incremental release-note changes; enabling ML-DSA APIs on JDK 24 but using JDK 21’s jarsigner for release gates.


KEM API: why KeyAgreement is not enough
#

Why: Modern protocols such as TLS 1.3 and HPKE center on KEM for symmetric key exchange; expressing encapsulation with RSA-encrypted random AES keys or misusing KeyAgreement is hard to audit and prone to side-channel and semantic errors.

Mechanism: Key encapsulation (KEM) encapsulates a symmetric key over an insecure channel—semantically preferable to the old pattern of “random symmetric key + RSA public-key encryption.” JEP 452 notes existing KeyAgreement, KeyGenerator, and Cipher are insufficient for KEM; hence javax.crypto.KEM with KEM.Encapsulator / KEM.Decapsulator.

KEM API slide: None of existing APIs were sufficient; two main classes KEM.Encapsulator / Decapsulator

Figure: KEM API JDK 21 — None of existing APIs (KeyAgreement, KeyGenerator, Cipher) were sufficient; two main classes: KEM.Encapsulator and KEM.Decapsulator.

JEP 452: Key Encapsulation Mechanism API — Release 21, modern cryptographic technique for securing symmetric keys

Figure: JEP 452: Key Encapsulation Mechanism API KEM API Owner Weijun Wang Type Feature JDK 21 Scope SE Status Closed/Delivered Release 21.

import javax.crypto.KEM;
import javax.crypto.SecretKey;

KEM kem = KEM.getInstance("ML-KEM");
KEM.Encapsulator enc = kem.newEncapsulator(peerPublicKey);
KEM.Encapsulated out = enc.encapsulate();
byte[] kemMessage = out.encapsulation();
SecretKey shared = out.key();

Common pitfalls: Calling KEM.getInstance("ML-KEM") on JDK 21—the algorithm implementation ships with JEP 496 in JDK 24. Slides mention API backport to JDK 17—not documented in JEP 452 text; for production baselines, check Oracle commercial update notes or label as speaker statement.


ML-KEM: parameter sets, PKI, and encapsulation direction
#

Why: HNDL scenarios need an interoperable lattice KEM; after FIPS 203 finalization the JDK delivers JCA standard names aligned with NIST test vectors and TLS drafts.

Mechanism: JEP 496 (JDK 24, security-libs/javax.crypto) implements FIPS 203 with parameter sets ML-KEM-512, ML-KEM-768, and ML-KEM-1024; default ML-KEM-768. keytool can generate ML-KEM key pairs and certificates, but ML-KEM is not a signature algorithm—certificates must be signed with RSA, ML-DSA, or similar—JEP text: cannot be used to sign the certificate containing the ML-KEM public key.

JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism ML-KEM — mechanism specified in FIPS 203

Figure: JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism ML-KEM … mechanism specified in FIPS 203.

Under draft-ietf-tls-ecdhe-mlkem semantics, the client key_share carries the encapsulation public key and the server returns ciphertext—consistent with sender encapsulate and receiver decapsulate roles at the API layer.

keytool -genkeypair -alias pq-ca -keyalg ML-DSA -groupname ML-DSA-65 \
  -dname "CN=PQ CA" -keystore ks -storepass changeit -ext bc:critical=ca:true
keytool -genkeypair -alias mlkem-ee -keyalg ML-KEM -groupname ML-KEM-768 \
  -signer pq-ca -keystore ks -storepass changeit
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM");
KeyPair clientKp = kpg.generateKeyPair();
KEM kem = KEM.getInstance("ML-KEM");
KEM.Decapsulator dec = kem.newDecapsulator(clientKp.getPrivate());
// SecretKey shared = dec.decapsulate(kemMsgFromServer);

Parameter set choice: ML-KEM-512 is smaller; ML-KEM-1024 offers higher security margin; the general default ML-KEM-768 aligns with NIST Level 3 narrative and the 768 instance in TLS hybrid groups. NamedParameterSpec constants such as ML_KEM_768 apply when explicitly calling initialize.

Common pitfalls: Self-signed ML-KEM certificates; or assuming JDK 24 enables PQ HTTPS by default—requires JDK 27 plus peer support for hybrid groups. Hard-coding “client decapsulate” from API demos into every protocol role—in pure KEM message protocols roles may differ; follow the protocol spec.


ML-DSA: signatures, JARs, and version forks
#

Why: Supply-chain signatures, code distribution, and TLS certificate chains have long relied on RSA/ECDSA; under a CRQC, verifiable post-quantum signatures aligned with FIPS 204 test vectors are needed.

Mechanism: JEP 497 (JDK 24, java.security) delivers FIPS 204 with parameter sets ML-DSA-44, ML-DSA-65, and ML-DSA-87; default ML-DSA-65. JEP 497 Non-Goals include ML-DSA support for JAR/TLS within JDK 24; jarsigner sign and verify with ML-DSA ships in JDK 26 release notes (RFC 9882).

JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm ML-DSA — specified in FIPS 204

Figure: JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm ML-DSA … lattice-based signature algorithm specified in FIPS 204.

jarsigner -sigalg ML-DSA-65 -keystore ks -storepass changeit test.jar ML-DSA \
  -signedjar signed.jar
jarsigner -verify -verbose signed.jar
import java.security.*;
import java.security.spec.NamedParameterSpec;

KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA");
kpg.initialize(new NamedParameterSpec("ML-DSA-65"));
KeyPair kp = kpg.generateKeyPair();
Signature sig = Signature.getInstance("ML-DSA");
sig.initSign(kp.getPrivate());
sig.update(messageBytes);
byte[] signatureBytes = sig.sign();

Stateful hash-based signatures HSS/LMS (RFC 8554) have a built-in verification path from JDK 21 onward; production signing and keytool generation of stateful key pairs usually still requires a third-party provider—mistaking “can jarsigner -verify an LMS JAR” for production signing capability can lead to key-reuse class incidents.

Common pitfalls: Requiring ML-DSA-signed JARs to pass in JDK 24 CI without upgrading to JDK 26.


KDF and HKDF: from KEM output to session keys
#

Why: KEM output is a short shared secret; protocols typically use HKDF to derive multiple keys (client/server write keys, IVs, finished labels, etc.). SecretKeyFactory targets password-storage scenarios such as PBKDF2 and cannot express extract-then-expand semantics.

Mechanism: javax.crypto.KDF fills the modern KDF abstraction; built-in HKDF (HKDF-SHA256/384/512) serves HPKE, TLS 1.3 hybrid exchange, and similar uses. JEP 510 states Argon2 is planned; as of JEP text it is not yet delivered as a built-in algorithm.

JEP 510: Key Derivation Function API — previewed in JEP 478 and finalized in Release 25

Figure: JEP 510: Key Derivation Function API KDF API Owner Kevin Driver … previewed in JEP 478 (JDK 24) and finalized in.

import javax.crypto.KDF;
import javax.crypto.spec.HKDFParameterSpec;

KDF hkdf = KDF.getInstance("HKDF-SHA384");
// HKDFParameterSpec: extract IKM may be KEM output; thenExpand derives AES keys, etc.
// SecretKey aesKey = hkdf.deriveKey("AES", spec);

JEP 510 explicitly lists TLS 1.3 (including hybrid key exchange) among target use cases for the KDF API; roadmap coupling with JEP 527 means underlying KDF finalization (25) precedes or runs in parallel with JSSE hybrid TLS (27)—most application developers still do not call HKDF directly, but custom protocol stacks (e.g., experimental PQ gRPC channels) will.

Common pitfalls: Depending on finalized KDF API in JDK 24 production code—finalization is in JDK 25. Shipping library artifacts on preview API without removing @PreviewFeature. Assuming Argon2 is built in—JEP expresses intent only; track follow-on JEPs.


HPKE: the KEM + KDF + AEAD triplet
#

Why: Applications often need “encrypt arbitrary-length plaintext to the recipient’s public key”; wrapping with AEAD atop the KEM layer is the standard approach in RFC 9180, avoiding ad hoc concatenation of KEM output and symmetric encryption.

Mechanism: RFC 9180 defines HPKE as a combination of KEM, KDF, and AEAD; JDK 26 exposes it via Cipher.getInstance("HPKE") and HPKEParameterSpec. RFC 9180 standardized profiles center on DHKEM (e.g., DHKEM(X25519, HKDF-SHA256)); it does not define an HPKE code point for ML-KEM—JDK 26 initial delivery is therefore mainly classical suites, with PQC profiles to extend after IETF finalizes RFCs—speaker/roadmap statement + RFC scope inference, not a separately citable JEP clause in this pass.

Hybrid Public Key Encryption (HPKE) JDK 26 — defined in RFC 9180, combining KEM, KDF, and AEAD

Figure: Hybrid Public Key Encryption (HPKE) JDK 26 — modern encryption scheme … defined in RFC 9180.

import javax.crypto.Cipher;
// Cipher hpke = Cipher.getInstance("HPKE");
// hpke.init(Cipher.ENCRYPT_MODE, recipientPublicKey, hpkeParameterSpec);

Common pitfalls: Calling getInstance("HPKE") without HPKEParameterSpec; expecting ML-KEM HPKE profiles on JDK 26—RFC 9180 currently standardizes the DHKEM family; PQC profiles await IETF additions.


TLS 1.3 post-quantum hybrid key exchange (JDK 27)
#

Why: For most Java microservices this is the main path to mitigate HNDL without business code changes: the handshake completes inside JSSE without the application calling KEM.encapsulate directly.

Mechanism: JEP 527 integrates hybrid key exchange into javax.net.ssl TLS 1.3: by default X25519MLKEM768 is first in the client offer list; also supports SecP256r1MLKEM768 and SecP384r1MLKEM1024 (the latter two are not enabled by default). Without manually restricting named groups, most applications gain hybrid protection without change to existing code; custom ordering uses SSLParameters.setNamedGroups or the system property jdk.tls.namedGroups.

Post-Quantum Hybrid Key Exchange for TLS 1.3 JDK 27 — protects against HNDL, support for X25519MLKEM768

Figure: Post-Quantum Hybrid Key Exchange for TLS 1.3 JDK 27 — combines classical and post-quantum key exchange algorithms; protects against HNDL.

jdk.tls.namedGroups=X25519MLKEM768,SecP256r1MLKEM768,SecP384r1MLKEM1024
import javax.net.ssl.*;

SSLParameters p = sslSocket.getSSLParameters();
p.setNamedGroups(new String[] { "SecP256r1MLKEM768", "X25519MLKEM768" });
sslSocket.setSSLParameters(p);

Mermaid diagram 2

Risk (JEP 527): IETF specifications remain draft; JDK behavior may change after RFC finalization. JEP Non-Goal includes pure ML-KEM TLS (non-hybrid).

With custom SSLEngine, Netty SslContext, or explicit jdk.tls.namedGroups, build an interop matrix: JDK 27 clients versus OpenSSL 3.5+, BoringSSL, and other peers differ in hybrid group support. FIPS 140 module certification boundaries—whether hybrid TLS falls inside module security policy—require HSM/JDK FIPS vendor answers, beyond generic OpenJDK documentation.

Common pitfalls: Upgrading only to JDK 27 without confirming load balancers, API gateways, or older Android/browsers support hybrid groups, leading to silent fallback to classic ECDHE. Setting jdk.tls.namedGroups to X25519 alone to “speed up,” which disables PQ protection.


Operations: observability and performance boundaries
#

Why: With fleets of hundreds of JVMs, you need proof that TLS was not quietly relaxed—not a single manual openssl s_client sample.

Mechanism: OpenJDK provides the JFR event jdk.TLSHandshake (fields include protocolVersion, cipherSuite, certificateId, etc.). The event does not include the negotiated named group—JFR alone cannot prove hybrid groups are in use; combine JDK 26+ java -XshowSettings:security:tls, packet capture, or vendor extension events. JEP 527 / this session did not provide quantitative PQ TLS handshake performance data—capacity planning should cite independent benchmarks; do not invent latency or throughput numbers.

java -XX:StartFlightRecording=duration=60s,filename=pq-tls.jfr -jar app.jar
java -XshowSettings:security:tls -version

Where named-group evidence is required, parse supported_groups / key_share in staging with Wireshark, or run a one-off probe against a test endpoint known to support hybrid groups. Q&A mentions of JFR for TLS observation should be read as protocol version, cipher suite, certificate fields, etc.; if the talk implied you can see X25519MLKEM768 at a glance, that may not match the current TLSHandshakeEvent field set—verify against source.

Common pitfalls: Capacity planning from handshake latency numbers not given in this session; writing Grover threats as “must immediately disable AES-128-GCM”—decide per protocol interop and performance budget.


Migration checklist (engineering view)
#

  1. Runtime: Plan JDK 27 (or an EA build with JEP 527) for outbound TLS; JDK 26+ for ML-DSA JAR signing pipelines; JDK 24+ for generating ML-KEM/ML-DSA key material.
  2. Edge and clients: Map L7/L4 termination proxies, service mesh, and mTLS mutual auth effects on named groups.
  3. PKI: Separate KEM certificate carriers from signing algorithms; CAs need ML-DSA (or transitional RSA) signing capability first.
  4. Supply chain: Align jarsigner -sigalg ML-DSA-65 with dependent JDK verification versions.
  5. Compliance ledger: Bind FIPS 203/204 numbers + IANA group names + JDK versions in three columns.
  6. Observability: JFR + security:tls settings + sampled captures—avoid single-signal false conclusions.

Capability iteration quick reference
#

CapabilityJDK versionBasis
KEM API21JEP 452
ML-KEM / ML-DSA algorithms24JEP 496 / 497
KDF finalized / HKDF25JEP 510
ML-DSA jarsigner26JDK 26 RN
HPKE Cipher26JDK 26 RN
PQ hybrid TLS27JEP 527

Early-access builds: jdk.java.net/27. Roadmap items such as PEM API, Argon2, TLS certificate compression, LMS RFC 9858, and jlink security plugins require per-JEP status checks—not verified in this article.


References and further reading
#

Related