The question reaches a bank's Java team from its security office: which of our systems still exchange keys or sign with RSA or elliptic curves, and when does that have to stop?
A PQC migration for a Java system starts with that inventory and with upgrades: find the cryptography, move to a JDK that ships the new algorithms, and make the algorithm a setting. Swapping algorithms is the short part.
Harvest now, decrypt later: which data in a financial system is exposed today
Public-key algorithms such as RSA, ECDH and ECDSA rest on problems a large enough quantum computer could solve. The NSA calls such a machine a cryptanalytically relevant quantum computer, and nobody can show one today. The risk for a bank starts earlier, because traffic and backups recorded now can be decrypted once such a machine exists. That is harvest now, decrypt later.
The EU coordinated roadmap turns it into a test you can apply to each system. A use case is high-risk "if compromising confidentiality after 10 years or more would still cause significant damage", and data that has to stay confidential that long "should be protected from quantum computer attacks starting no later than by the end of 2030".
In a financial system that covers more than people expect: account and transaction history, KYC files, loan agreements, card data kept for disputes, the internal traffic between services that carries all of it. The FastPost ledger we built for Legerity has been in production since 2013, which is longer than the ten years in that test.
Signatures are a different case. A forged signature needs the quantum computer to exist at the moment of forgery, so recorded traffic is not at risk. What is at risk is a signature that has to stay verifiable for decades, such as a signed loan agreement or an audit trail.
Symmetric encryption stays. NIST's transition plan keeps AES-256 in its highest security category, so the data itself stays encrypted with AES. The migration concerns how the AES keys are exchanged, wrapped and signed.
PQC migration deadlines: NIST, the EU roadmap and the UK NCSC
NIST published the first post-quantum standards on 13 August 2024: FIPS 203 for key encapsulation (ML-KEM) and FIPS 204 for signatures (ML-DSA), with FIPS 205 as a hash-based signature alternative. The dates for retiring the old algorithms are in NIST IR 8547, still an initial public draft from November 2024: RSA and elliptic-curve algorithms at the 112-bit security level, which covers 2048-bit RSA keys, are deprecated after 2030, and all of them are disallowed after 2035.
European banks and insurers will be asked about the EU roadmap of June 2025 first. Member states should start the transition by the end of 2026, finish high-risk use cases by the end of 2030, and medium-risk ones by the end of 2035. The UK National Cyber Security Centre sets the same end date, with discovery and a plan by 2028 and the priority migrations by 2031.
The NSA's CNSA 2.0, announced in September 2022, sets the algorithms for US national security systems. A commercial bank is outside its scope, so it appears here only because suppliers to both markets quote it.
For budgeting, the date that matters is the end of 2030. Any system that keeps data confidential for ten years or more is high-risk under the EU test, and four years is not long for a bank to change how every service exchanges keys.
Building a cryptographic inventory of a Java system
A cryptographic inventory lists every place a system encrypts, signs or exchanges keys, with the algorithm, the key size, the library and the data it protects. For a Java application that means five places:
- Code that calls the Java Cryptography Architecture directly:
Cipher,Signature,KeyPairGenerator,KeyAgreement. - Libraries that bring their own cryptography: Bouncy Castle, JWT libraries, SAML and XML signature stacks, database drivers with their own TLS.
- Keystores and certificates, including the ones a partner gave you years ago.
- TLS endpoints in both directions: the ones you serve and the outbound calls to payment networks, credit bureaus and other partners.
- Stored data whose keys are wrapped or signed with RSA or elliptic curves: field-level encryption, archived documents, signed records.
CycloneDX, the SBOM standard, defines a Cryptography Bill of Materials (CBOM) for this: "algorithms, keys, certificates, and their relationships to software components". A CBOM is worth keeping for the same reason as an SBOM. The inventory goes out of date with every release, and a machine-readable one can be regenerated in the build.
Commands for a first pass
These four commands find most of it in a Maven project. They give a first draft of the inventory: a provider configured in a properties file or an algorithm read from a database will not show up in a grep.
# 1. Where the code calls the JCA with a quantum-vulnerable algorithm
grep -rnE 'getInstance\("(RSA|EC|ECDSA|ECDH|DH|DSA|Ed25519|EdDSA|X25519|SHA(256|384|512)with(RSA|ECDSA))' \
--include=*.java src/
# 2. Libraries that bring their own cryptography
mvn dependency:tree -Dincludes=org.bouncycastle,com.nimbusds,io.jsonwebtoken
# 3. Keys and certificates in a keystore
keytool -list -v -keystore keystore.p12 | grep -E 'Alias name|Signature algorithm|Subject Public Key Algorithm'
# 4. The key exchange each TLS connection negotiates
java -Djavax.net.debug=ssl:handshake -jar app.jar 2>&1 | grep -A1 '"server_share"'
The keystore listing shows both kinds of key side by side once you start migrating. On Java 25, a keystore holding a 2048-bit RSA key and an ML-DSA key reports Signature algorithm name: SHA384withRSA with Subject Public Key Algorithm: 2048-bit RSA key for the first, and ML-DSA-65 for the second.
What the JDK gives you: ML-KEM, ML-DSA and X25519MLKEM768
| Release | What it adds | What it means in practice |
|---|---|---|
| JDK 24 (March 2025) | ML-KEM (JEP 496) and ML-DSA (JEP 497) in the standard providers | Post-quantum key encapsulation and signatures with no extra library; not used by TLS |
| Java 25 (LTS, September 2025) | The same algorithms | The first long-term support release that has them |
| JDK 27 (15 September 2026) | Hybrid key exchange for TLS 1.3 (JEP 527): X25519MLKEM768, enabled by default and first in the list | Every javax.net.ssl connection to a server that supports it becomes quantum-safe for key exchange, with no code change |
| Java 25.0.5 (planned for 20 October 2026) | JEP 527 backported | Hybrid TLS on the current LTS release |
| Oracle JDK 21.0.14 and 17.0.22 (planned for 19 January 2027) | JEP 527 backported to Oracle's builds | Hybrid TLS for teams on Oracle's paid updates for 17 or 21 |
X25519MLKEM768 is a hybrid: it combines classical X25519 with ML-KEM-768, so the connection stays as secure as today's even if a flaw turns up in the newer algorithm. We checked the difference on 11 October 2026 with a plain SSLSocket to www.cloudflare.com. On JDK 27 the handshake negotiated X25519MLKEM768; on Temurin 25.0.4, which does not have the backport yet, it negotiated classical x25519.
The JDK only matters where Java terminates TLS. If a load balancer, an API gateway or a service mesh sidecar terminates it in front of your application, that component needs the upgrade, and the inventory has to say which one it is.
Systems that cannot leave Java 17 or 21 yet, and do not run Oracle's builds, can use Bouncy Castle (release 1.86 on Maven Central) for ML-KEM and ML-DSA in application code. Use the FIPS names and implementations: older libraries and many examples still say Kyber and Dilithium, the names from the competition, which may refer to versions before the final standards.
Crypto agility in Spring Boot: the four InfoQ patterns
Pankaj Sharma's InfoQ article (August 2026) describes four places a Spring Boot application in banking can add post-quantum cryptography in application code:
- Request bodies between internal services encrypted with an ML-KEM-derived AES-256-GCM key, as a second layer under TLS.
- PII and KYC fields encrypted before they are written through JPA.
- Loan agreements and audit trails signed at the moment they are created.
- Service JWTs signed with a post-quantum algorithm in place of RS256.
The article is also blunt about what comes first: "Get AWS KMS or HashiCorp Vault in place for Kyber key management. Nothing else is production-safe without this change." A post-quantum private key in a properties file is no safer than an RSA key in one.
The code below uses the JDK's own providers on Java 25 and runs as shown. The key encapsulation produces an AES key; the signature algorithm is read from configuration, which is what crypto agility means in practice: changing algorithms takes a configuration change and a deployment.
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.util.Arrays;
import javax.crypto.KEM;
import javax.crypto.SecretKey;
public class PqcDemo {
public static void main(String[] args) throws Exception {
// Key encapsulation (FIPS 203). The receiver publishes an ML-KEM public key.
KeyPair receiver = KeyPairGenerator.getInstance("ML-KEM").generateKeyPair(); // ML-KEM-768
KEM.Encapsulated sent = KEM.getInstance("ML-KEM")
.newEncapsulator(receiver.getPublic())
.encapsulate();
SecretKey senderKey = sent.key(); // a 256-bit secret, used as an AES-GCM key
byte[] encapsulation = sent.encapsulation(); // sent to the receiver
SecretKey receiverKey = KEM.getInstance("ML-KEM")
.newDecapsulator(receiver.getPrivate())
.decapsulate(encapsulation);
System.out.printf("ML-KEM: encapsulation %d bytes, keys match: %b%n", encapsulation.length,
Arrays.equals(senderKey.getEncoded(), receiverKey.getEncoded()));
// Signatures (FIPS 204). The algorithm comes from configuration, not from the code.
String keyAlg = System.getProperty("signing.key-algorithm", "ML-DSA");
String sigAlg = System.getProperty("signing.signature-algorithm", "ML-DSA");
KeyPair signer = KeyPairGenerator.getInstance(keyAlg).generateKeyPair();
byte[] document = "Loan agreement 2026-0412".getBytes();
Signature sign = Signature.getInstance(sigAlg);
sign.initSign(signer.getPrivate());
sign.update(document);
byte[] signature = sign.sign();
Signature verify = Signature.getInstance(sigAlg);
verify.initVerify(signer.getPublic());
verify.update(document);
System.out.printf("%s: signature %d bytes, valid: %b%n", sigAlg, signature.length, verify.verify(signature));
}
}
$ java PqcDemo
ML-KEM: encapsulation 1088 bytes, keys match: true
ML-DSA: signature 3309 bytes, valid: true
$ java -Dsigning.key-algorithm=RSA -Dsigning.signature-algorithm=SHA256withRSA PqcDemo
ML-KEM: encapsulation 1088 bytes, keys match: true
SHA256withRSA: signature 384 bytes, valid: true
The sizes are the part that breaks things. An ML-DSA signature is 3,309 bytes against 384 for the RSA signature from the same program, and a JWT carries it in Base64. Check every header size limit between the token issuer and the service that verifies it, and every database column sized for an RSA signature, before the fourth pattern goes live.
Agility also needs a record of which algorithm produced each stored ciphertext or signature. Without one, the next change of algorithm means guessing what was used for data written ten years earlier.
PQC migration checklist: the order of work
This is the order we would follow for a Java platform in banking or insurance. Each step depends on the one before it.
- Build the cryptographic inventory and generate a CBOM in the build.
- Classify each use case by how long its data must stay confidential, using the EU's ten-year test.
- Upgrade to a JDK that has ML-KEM and ML-DSA: Java 25 now, 25.0.5 or later for hybrid TLS.
- Turn on hybrid TLS wherever Java terminates connections, and list the load balancers and gateways that need their own upgrade.
- Move keys into a KMS or an HSM before introducing any new key type.
- Add an algorithm identifier to every stored ciphertext and signature, and read algorithm names from configuration.
- Re-encrypt long-lived data so its AES keys are protected with ML-KEM, starting with the high-risk use cases.
- Add ML-DSA signatures next to the existing ones on documents that must stay verifiable for decades.
- Change tokens last, once every service that verifies them accepts the new algorithm and the larger size.
- Load-test each step: larger handshakes, keys and signatures change latency and storage.
How we would run a PQC migration on your platform
We treat a PQC migration like any other upgrade of a long-lived Java system: measured first, then done in tested steps. It starts with a paid baseline review that produces the inventory, the risk class of each use case and a remediation plan, and the upgrade phases are scoped and priced separately. For the general hardening that should come with it, see our guide to securing Java applications.
If your security office has started asking which systems still depend on RSA, our Java vulnerability remediation service begins with that baseline review, scoped on a thirty-minute call.