Java 21 Key Encapsulation Mechanism (KEM) API
Secure communication relies on exchanging cryptographic keys safely over untrusted networks. Until Java 21, implementing this in Java required combining multiple low-level APIs such as Cipher, KeyAgreement, and KeyGenerator, often leading to complexity. To solve this, Java now includes a standardised Key Encapsulation Mechanism (KEM) API as part of JEP 452. This new API provides a clean and consistent approach for establishing shared symmetric keys using public-key cryptography.
1. Why KEM
Before Java 21, the platform lacked native support for key encapsulation, requiring developers to implement custom key exchange workflows. These manual approaches often differed between cryptographic providers and increased the likelihood of errors or security vulnerabilities.
The introduction of the KEM API changes this by providing a standardised, provider-neutral mechanism for secure key establishment. It works consistently across supported algorithms, including RSA-KEM, ECIES, and Diffie-Hellman KEM (DHKEM), aligning with modern cryptography standards while reducing implementation complexities. KEMs also integrate seamlessly into higher-level protocols such as TLS and Hybrid Public Key Encryption (HPKE, RFC 9180).
Providers can implement KEM algorithms in Java or native code, offering both portability and performance, and the API is extensible to future post-quantum cryptography standards, ensuring long-term security and compatibility.
2. How KEM Works (Conceptually)
KEM establishes a shared symmetric key using three simple cryptographic steps:
- Create a key pair: The recipient generates an asymmetric key pair consisting of a public key for distribution and a private key kept secret. This pair enables secure key establishment without revealing sensitive information.
- Encapsulate a shared key: The sender uses the recipient’s public key to generate a fresh symmetric key along with a compact encapsulated message. Only the encapsulated output is transmitted, while the secret key remains with the sender.
- Decapsulate to recover the key: Using their private key, the recipient processes the encapsulated message to retrieve an identical symmetric key. Both sides now securely share a key without sending it directly over the network.
This process ensures confidentiality and prevents key exposure, making KEM a reliable foundation for secure communication protocols and encrypted data exchange.
3. Available KEM Algorithms in Java 21
Java 21 includes support for widely accepted KEM algorithms, such as:
| Algorthim | Category | Standard/Reference | Status |
|---|---|---|---|
| RSA-KEM | Based on RSA | RFC 5990 | Supported |
| ECIES | Elliptic-curve scheme | IEEE Std 1363 | Supported |
| DHKEM | Diffie-Hellman KEM | RFC 9180 | Included |
| PQC KEMs | Post-quantum candidates | NIST PQC process | Extensible via providers |
4. Working with the KEM API in Java 21
This flow shows how two parties use KEM to securely derive the same symmetric key using an RSA-based KEM implementation.
Step 1 – Generate a Key Pair
The recipient creates an asymmetric key pair that will be used for secure key encapsulation.
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("X25519");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
This code snippet initialises a key pair generator for the X25519 elliptic-curve algorithm. It generates a new asymmetric key pair, producing a public key for sharing and a private key to keep secret, which together can be used for secure key exchange or encapsulation operations.
Step 2 – Select and Initialise a KEM Algorithm
Java 21 currently supports algorithms like RSA-KEM, EC-based KEMs, and DHKEM.
KEM kem = KEM.getInstance("DHKEM");
This line creates an instance of the Key Encapsulation Mechanism (KEM) using the Diffie-Hellman KEM (DHKEM) algorithm.
Step 3 – Encapsulate a Secret Key (Sender Side)
The sender uses the recipient’s public key to generate:
- A new symmetric key
- An encapsulated message (safe to transmit)
KEM.Encapsulated encapsulation = kem.newEncapsulator(keyPair.getPublic())
.encapsulate();
byte[] capsule = encapsulation.encapsulation();
The capsule is sent to the recipient over the network.
Step 4 – Decapsulate the Shared Key (Recipient Side)
The recipient uses their private key to recover the same symmetric key from the capsule.
KEM.Decapsulator decapsulation = kem.newDecapsulator(keyPair.getPrivate());
SecretKey receiverSecret = decapsulation.decapsulate(capsule);
Result
Both parties now hold an identical symmetric key.
| Sender Key | Receiver Key | Status |
|---|---|---|
| Derived using public key | Derived using private key | Keys match |
This shared key can then be used to encrypt data, secure a session, or authenticate communication, all without ever sending the secret directly.
Putting It All Together: Java Program KEM Example
This program generates an RSA key pair, performs key encapsulation and decapsulation to derive a symmetric secret, and verifies that both parties hold the same shared key.
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Arrays;
import javax.crypto.KEM;
import javax.crypto.SecretKey;
public class JavaKemDemo {
public static void main(String[] args) throws Exception {
// Generate RSA Key Pair
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("X25519");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// Initialize the KEM API
KEM kem = KEM.getInstance("DHKEM");
// Sender encapsulates a shared secret key
KEM.Encapsulated encapsulation = kem.newEncapsulator(keyPair.getPublic())
.encapsulate();
SecretKey senderSecret = encapsulation.key();
byte[] capsule = encapsulation.encapsulation();
System.out.println("Capsule: " + Arrays.toString(capsule));
System.out.println("Sender Secret: " + Arrays.toString(senderSecret.getEncoded()));
// Receiver decapsulates to recover the same secret
KEM.Decapsulator decapsulation = kem.newDecapsulator(keyPair.getPrivate());
SecretKey receiverSecret = decapsulation.decapsulate(capsule);
System.out.println("Receiver Secret: " + Arrays.toString(receiverSecret.getEncoded()));
// Confirm they match
boolean match = Arrays.equals(senderSecret.getEncoded(), receiverSecret.getEncoded());
System.out.println("\nSame shared key? " + (match ? "YES" : "NO"));
}
}
Example Output
Capsule: [-58, -18, 101, 46, -14, 9, -7, -95, 28, 58, 102, -93, 30, 119, -71, -112, -113, 49, 88, -76, 89, 27, 59, 55, 75, -46, -82, 48, 127, -56, 12, 5] Sender Secret: [-79, -71, 33, 85, -36, -93, -33, -36, 102, -60, -54, 1, 24, -69, 124, 75, -115, 8, 101, -102, -106, 18, -125, -21, -55, 28, 124, -79, -74, 66, 81, 6] Receiver Secret: [-79, -71, 33, 85, -36, -93, -33, -36, 102, -60, -54, 1, 24, -69, 124, 75, -115, 8, 101, -102, -106, 18, -125, -21, -55, 28, 124, -79, -74, 66, 81, 6] Same shared key? YES
This output shows that the sender generated a symmetric secret key and encapsulated it into a capsule, which the receiver successfully decapsulated using their private key, resulting in identical secret keys on both sides, confirming a secure key exchange.
4. Conclusion
In this article, we explored the Java Key Encapsulation Mechanism (KEM) API introduced in Java 21, demonstrating how it standardises secure key exchange using algorithms like RSA-KEM, ECIES, and DHKEM. By walking through key pair generation, encapsulation, and decapsulation, the article showed how we can safely establish shared symmetric keys without exposing sensitive data.
The KEM API simplifies cryptographic implementations, supports integration with protocols such as TLS, and provides a future-ready foundation for both classical and post-quantum secure communication.
5. Download the Source Code
You can download the full source code of this example here: java key encapsulation mechanism api

