Most of us use our computer generated public/private key pairs to access cloud-based SAAS services, connect to cloud-based virtual machines, securely transfer files/data, encrypt sensitive data/network connections and digitally sign documents.
There is a lot of mathematics and computing that goes on underneath all this, and of late there are new and potentially very dangerous threats that are emerging for encryption key pairs.
In this post we discuss some of the inner mechanisms, and how to protect your keys from threats in the near future.
How are Messages Encrypted, Sent and Deciphered?
From a bird’s eye view, the sender of a file/message/packet encrypts the packet using his private key and the receiver’s public key. Then he sends his public key and this encrypted packet to the receiver. The receiver uses his own private key and the sender’s public key to decrypt this encrypted packet, and can view the information.
An Introduction to the Process of Key Exchange in Public Key Cryptography
Both the sender and receiver generate their own respective pairs of public and private keys, running a key pair generation function at their respective ends. Then they exchange their public keys, but each party keeps its private key secure.
The process starts with the prospective receiver of the encrypted message: first the receiver sends his public key to the potential sender. The sender accepts the receiver’s public key, combines it with the message/file to be encrypted and his own private key, and calls a key encapsulation function. This key encapsulation function then returns a secret key K and an encapsulated object to its caller. The sender sends the encapsulated object to the receiver.
The receiver on his end takes the received encapsulated object , combines it with his private key, and calls a key decapsulation function with secret key K and the encapsulated object as parameters . This key decapsulation function returns the secret message to the receiver.
So, in this whole process, the private key of each party is never exchanged/sent over the network. The private keys are kept in safe custody with their respective owners only, and used to call the key encapsulation/decapsulation functions.
If a secure network connection is to be established between two parties, a shared secret key is established over a public channel via KEM (Key Encapsulation Mechanism), and this shared secret key is used every time data is sent over this secure channel.
The most widely used public-key based algorithms are Rivest-Shamir-Adleman (RSA) and Diffie-Hellman. As of now, it’s almost impossible to penetrate/beat these algorithms using the computing power available today.
But there is another algorithm, called the Shor’s algorithm, that can break the existing public-key cryptography schemes such as RSA and Diffie-Hellman, as well as the elliptic-curve Diffie–Hellman key exchange mechanisms, if its run on a quantum computer with a sufficient number of qubits. Given a quantum computer, the Shor’s algorithm could operate without succumbing to quantum noise and other quantum-decoherence phenomena, and break the existing KEMs (key encapsulation mechanisms).

Fig: Composite KEM
What are the Potential Current and Future Risks to my Cryptography Keys and Encrypted Data?
Today, there are no quantum computers available, and even today’s supercomputers would need a few thousand years to break the KEMs. But a hacker may store your keys and your encrypted data today for future exploitation; and as soon as a quantum computer is available in future, he could decrypt it and your confidential information will be easily divulged.
Not only this, public key cryptography and KEMs are used today to sign JAR files and to establish secure network connections via the Transport Layer Security (TLS) protocol, amongst other sensitive/confidential uses. All this will become truly vulnerable when quantum computers are available.
Without going into too many intrinsic details, we will next discuss what should be done to mitigate the above risks.
What Can I Do Today to Secure My Cryptography Keys and Encrypted Data?
Cryptographers have responded to this impending threat by inventing quantum-resistant cryptographic algorithms, which cannot be defeated by Shor’s algorithm.
Java, being a responsible ecosystem, has responded by implementing the Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM) to exchange keys in a quantum-resistant fashion, in its latest release, Java 24.
More about ML-KEM can be found on the NIST (National Institute of Standards and Technology) website.
ML-KEM is built on top of the component public-key encryption scheme K-PKE; this scheme has two additional key types: encryption keys and decryption keys. In common terminology,
encapsulation keys and encryption keys are referred to as “public keys,” while decapsulation keys and decryption keys are referred to as “private keys.”
To generate an ML-KEM key, a cryptographically-secure pseudo-random number generator (CSPRNGs) is used to sample the 64 octets uniformly for the seed or private key. This private key is then used to compute the public key. Now the message/text encrypted using this private key can be decrypted. .
The Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM) is proven to be a quantum-resistant key-encapsulation, which even the Shor’s algorithm cannot beat.
There is sufficient evidence to believe that ML-KEM is secure, even against adversaries who possess a quantum computer. Also, there is sufficient research and evidence to presume that ML-KEM will be resistant and safe against any future mischievous algorithms.
Hence, it is standardized by the US National Institute of Standards and Technology (NIST) PQC Project [NIST-PQC].
ML-KEM uses lattice-based cryptography, and relies on the difficulty of solving the Module Learning with Errors (MLWE) problem (a variant of the Learning With Errors (LWE) problem), even for quantum computers.
Today, ML-KEM can be used to establish a shared secret key between two parties over an insecure channel. ML-KEM-based certificates are used in protocols where the public key is used to generate and encapsulate a shared secret, which in turn is used to derive a symmetric key used to encrypt a payload.
Right now, ML-KEM certificates cannot be used in transport layer security(TLS), but there are plans to upgrade this protocol to do so.
How are Encryption Keys Generated, in Simple Terms?
The security of ML-KEM is based on the presumed hardness of the so-called Module Learning with Errors (MLWE) problem, which itself is a generalization of the Learning With Errors (LWE) problem.
The mathematical concepts working under the hood are very complex to discuss in this post, but we will try to simplify and put them in layman’s terms.
In LWE problems, we have a set of “noisy” linear equations in some secret variables X/N/Q, such that s 𝑥 ∈ ℤ𝑛 𝑞 , and we use these equations to recover 𝑥.
Noisy linear equations are linear equations where the coefficients and/or the right-hand side terms are not exactly known,and could have some degree of error or uncertainty. This uncertainty is often modeled as random noise or disturbances.
Here, the noise is such that standard algorithms, like Gaussian elimination, cannot solve these equations. In other words, it’s computationally expensive or unreliable to try and find 𝑥 using these equations because of this noise. So, this fact makes these “noisy” linear equations perfect for cryptographic applications.
If we consider 𝑥 as our secret key, then we can encrypt a 1-bit plain text value by sampling either an approximately correct linear equation (if the plain text is zero) OR a far-from-correct linear equation (if the plain text is one). Then we send a large set of such “noisy” linear equations to the other (receiving) party as the public key.
The receiving party will be able to distinguish between “approximately correct” (0) and “far from correct” (1) ONLY if they already have the secret key 𝑥.
This concept is developed further to prepare the complementary set of public and private keys ( something like twins). Anything encrypted using the public key can only be decrypted using its twin private key.
The above is a gross simplification of the public key cryptography process. Those interested in details can refer to this PDF: ML-KEM Standards.
Show me Some Sample Code That Uses ML-KEM Keys
The following program generates an ML-KEM key pair at the receiver side, and sends the public key to the sender. Using the receiver’s public key, the sender encrypts some data to get an “encapsulated” shared secret. Then, at the receiver side, we used the receivers private key to decapsulate the shared secret. Lastly we check if the shared secret is actually what the sender sent.
import java.security.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.NamedParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.KEM.*;
import javax.crypto.KEM;
import javax.crypto.KEM.Encapsulated;
import javax.crypto.KEM.Decapsulator;
import javax.crypto.KEM.Encapsulator;
import java.util.Base64;
public class MLKEMKeys {
public static void main(String[] args) {
try {
// Generate ML-KEM key pair at the Receiver side ML_KEM_512
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ML-KEM-512");
//keyPairGenerator.initialize(NamedParameterSpec.ML-KEM-512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
System.out.println("This is how ML-KEM keys look: Public -- " + keyPair.getPublic() + " \n Private -- " + keyPair.getPrivate() );
// Encapsulate a shared secret
KEM kem = KEM.getInstance("ML-KEM-512");
KEM.Encapsulator encapsulator = kem.newEncapsulator(keyPair.getPublic());
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
byte[] sharedSecret = encapsulated.encapsulation();
SecretKey encapsulatedKey = encapsulated.key();
// Decapsulate the shared secret
KEM.Decapsulator decapsulator = kem.newDecapsulator(keyPair.getPrivate());
SecretKey secretKey = decapsulator.decapsulate(encapsulated.encapsulation());
// Verify that the shared secrets match
boolean secretsMatch = encapsulatedKey.equals(secretKey);
System.out.println("Shared secrets match: " + secretsMatch);
byte[] encodedKey = secretKey.getEncoded();
String base64EncodedKey = Base64.getEncoder().encodeToString(encodedKey);
byte[] decapsulatedKey = encapsulatedKey.getEncoded();
String base64DecapsulatedKey = Base64.getEncoder().encodeToString(decapsulatedKey);
System.out.println("Base64 encoded Secret key: " + base64EncodedKey);
System.out.println("Base64 encoded Decapsulated key: " + base64DecapsulatedKey);
// Example of using the shared secret to encrypt data (using AES for example)
if (secretsMatch) {
String plaintext = "This is a secret after-match message.";
System.out.println("Original Encapsulated Key : " + encapsulatedKey);
System.out.println("Secret Key from Decrypted data: " + secretKey);
}
else {
System.out.println(" Decapsulate3d Secret key - " + secretKey ) ; System.out.println("Original Encapsulated Key : " + encapsulatedKey);
System.out.println(" Key encapsulation message, if any - " + sharedSecret ) ;
}
} catch (NoSuchAlgorithmException e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
System.err.println("An unexpected error occurred: " + e.getMessage());
e.printStackTrace();
}
}
}
Tell Me Some Salient Features of ML-KEM Keys
ML-KEM keys are:
- Quantum-safe: Resistant to Shor’s and Grover’s algorithms.
- Efficient: Small key sizes and fast computation.
- Standardized: NIST’s Round 3 winner for KEMs.
- The ML-KEM standard specifies three parameter sets for the keys, in order of increasing security strength and decreasing performance. These are ML-KEM-512, ML-KEM-768, and ML-KEM-1024.
| Variant | Security Level | Public Key Size | Ciphertext Size | Shared Secret | Decapsulation failure rate |
| ML-KEM-512 | ~128-bit | 800 bytes | 768 bytes | 32 bytes | 2^138.8 |
| ML-KEM-768 | ~192-bit | 1,184 bytes | 1,088 bytes | 32 bytes | 2^164.8 |
| ML-KEM-1024 | ~256-bit | 1,568 bytes | 1,568 bytes | 32 bytes | 2^174.8 |
Conclusion
We have discussed a futuristic and very useful feature of Java 24, namely support for quantum-resisting cryptography, with some real-world code.
I hope this helps you get started with ML-KEM keys.

Share your Thoughts!