JEP 452, Key Encapsulation Mechanism API, has been promoted from Targeted to Completed for JDK 21. This JEP introduces an API for Key Encapsulation Mechanisms (KEMs), a modern encryption technique for securing symmetric keys using public key cryptography. The new API aims to enable applications to use KEM algorithms such as RSA Key Encapsulation Mechanism (RSA-KEM), Elliptic Curve Integrated Encryption Scheme (ECIES), and candidate KEM algorithms for the National Institute of Standards and Technology (NIST) Post-Quantum Cryptography standardization process.
KEMs are a crucial tool for defending against quantum attacks. The traditional technique of securing symmetric keys involves encrypting a randomly generated symmetric key with a public key. However, this requires padding and can be challenging to prove secure. KEMs, on the other hand, use properties of the public key to derive a related symmetric key, eliminating the need for padding.
The new API will also enable the use of KEMs in higher-level protocols such as Transport Level Security (TLS) and in cryptographic schemes such as Hybrid Public Key Encryption (HPKE, RFC 9180). It will allow security providers to implement KEM algorithms in either Java code or native code. However, it is not a goal to include key pair generation in the KEM API, as the existing KeyPairGenerator
API is sufficient.
The KEM API consists of three functions: a key pair generation function, a key encapsulation function, and a key decapsulation function. The key pair generation function is covered by the existing KeyPairGenerator
API, while the encapsulation and decapsulation functions are defined in a new class, KEM. Consider the following code snippets:
package javax.crypto;
public class DecapsulateException extends GeneralSecurityException;
public final class KEM {
public static KEM getInstance(String alg)
throws NoSuchAlgorithmException;
public static KEM getInstance(String alg, Provider p)
throws NoSuchAlgorithmException;
public static KEM getInstance(String alg, String p)
throws NoSuchAlgorithmException, NoSuchProviderException;
public static final class Encapsulated {
public Encapsulated(SecretKey key, byte[] encapsulation, byte[] params);
public SecretKey key();
public byte[] encapsulation();
public byte[] params();
}
public static final class Encapsulator {
String providerName();
int secretSize(); // Size of the shared secret
int encapsulationSize(); // Size of the key encapsulation message
Encapsulated encapsulate();
Encapsulated encapsulate(int from, int to, String algorithm);
}
public Encapsulator newEncapsulator(PublicKey pk)
throws InvalidKeyException;
public Encapsulator newEncapsulator(PublicKey pk, SecureRandom sr)
throws InvalidKeyException;
public Encapsulator newEncapsulator(PublicKey pk, AlgorithmParameterSpec spec,
SecureRandom sr)
throws InvalidAlgorithmParameterException, InvalidKeyException;
public static final class Decapsulator {
String providerName();
int secretSize(); // Size of the shared secret
int encapsulationSize(); // Size of the key encapsulation message
SecretKey decapsulate(byte[] encapsulation) throws DecapsulateException;
SecretKey decapsulate(byte[] encapsulation, int from, int to,
String algorithm)
throws DecapsulateException;
}
public Decapsulator newDecapsulator(PrivateKey sk)
throws InvalidKeyException;
public Decapsulator newDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)
throws InvalidAlgorithmParameterException, InvalidKeyException;
}
The getInstance
methods create a new KEM object that implements the specified algorithm. The sender calls one of the newEncapsulator
methods, which takes the receiver's public key and returns an Encapsulator
object. The sender can then call one of that object's encapsulate methods to get an Encapsulated
object, which contains a SecretKey
and a key encapsulation message.
The receiver calls one of the newDecapsulator
methods, which takes the receiver's private key and returns a Decapsulator
object. The receiver can then call one of that object's decapsulate
methods, which takes the received key encapsulation message and returns the shared secret.
The introduction of the KEM API in OpenJDK is a significant step forward in modern cryptography, providing a more secure and efficient way to secure symmetric keys using public key cryptography. It is expected to play a crucial role in defending against quantum attacks and enhancing the security of higher-level protocols and cryptographic schemes.