Cipher for the
Hybrid Public Key Encryption
(HPKE) algorithm. HPKE is a public key encryption scheme for encrypting
arbitrary-sized plaintexts with a recipient's public key. It combines a key
encapsulation mechanism (KEM), a key derivation function (KDF), and an
authenticated encryption with additional data (AEAD) cipher.
The
standard algorithm name for the cipher is "HPKE". Unlike most other
ciphers, HPKE is not expressed as a transformation string of the form
"algorithm/mode/padding". Therefore, the argument to Cipher.getInstance
must be the single algorithm name "HPKE".
In HPKE, the sender's Cipher is always initialized with the
recipient's public key in encrypt mode,
while the recipient's Cipher object is initialized with its own
private key in decrypt mode.
An HPKEParameterSpec object must be provided at HPKE
cipher initialization.
The of(int, int, int) static method returns an HPKEParameterSpec
object with the specified KEM, KDF, and AEAD algorithm identifiers.
The terms "KEM algorithm identifiers", "KDF algorithm identifiers", and
"AEAD algorithm identifiers" refer to their respective numeric values
(specifically, kem_id, kdf_id, and aead_id) as
defined in Section 7
of RFC 9180 and maintained on the
IANA HPKE page.
Once an HPKEParameterSpec object is created, additional methods
are available to generate new HPKEParameterSpec objects with
different features:
withInfo(byte[]) method by both sides.
mode_psk), the
pre-shared key and its identifier must be provided using the
withPsk(SecretKey, byte[]) method by both sides.
mode_auth),
the asymmetric keys must be provided using the withAuthKey(AsymmetricKey)
method. Precisely, the sender must call this method with its own private key
and the recipient must call it with the sender's public key.
mode_auth_psk), both withAuthKey(AsymmetricKey) and
withPsk(SecretKey, byte[]) methods must be called as described above.
Cipher#getIV() method. On the recipient side,
this message must be supplied as part of an HPKEParameterSpec
object obtained from the withEncapsulation(byte[]) method.
info, psk, and psk_id or matching authentication
keys if provided. For details about HPKE modes, refer to
Section 5
of RFC 9180.
If an HPKE cipher is initialized without
parameters, an InvalidKeyException is thrown.
At HPKE cipher initialization, if no HPKE implementation supports the
provided key type, an InvalidKeyException is thrown. If the provided
HPKEParameterSpec is not accepted by any HPKE implementation,
an InvalidAlgorithmParameterException is thrown. For example:
withAuthKey(key) is made with an incompatible key.
withAuthKey(key) is made but mode_auth
or mode_auth_psk is not supported by the KEM algorithm used.
doFinal calls, optionally preceded
by one or more updateAAD and update. Each doFinal
performs a complete HPKE encryption or decryption operation using a distinct
IV derived from an internal sequence counter, as specified in
Section 5.2
of RFC 9180. On the recipient side, each doFinal call must correspond
to exactly one complete ciphertext, and the number and order of calls must
match those on the sender side. This differs from the direct use of an AEAD
cipher, where the caller must provide a fresh IV and reinitialize the cipher
for each message. By managing IVs internally, HPKE allows a single
initialization to support multiple messages while still ensuring IV
uniqueness and preserving AEAD security guarantees.
This example shows a sender and a recipient using HPKE to securely exchange messages with an X25519 key pair.
// Recipient key pair generation KeyPairGenerator g = KeyPairGenerator.getInstance("X25519"); KeyPair kp = g.generateKeyPair(); // The HPKE sender cipher is initialized with the recipient's public // key and an HPKEParameterSpec using specified algorithm identifiers // and application-supplied info. Cipher senderCipher = Cipher.getInstance("HPKE"); HPKEParameterSpec ps = HPKEParameterSpec.of( HPKEParameterSpec.KEM_DHKEM_X25519_HKDF_SHA256, HPKEParameterSpec.KDF_HKDF_SHA256, HPKEParameterSpec.AEAD_AES_128_GCM) .withInfo(HexFormat.of().parseHex("010203040506")); senderCipher.init(Cipher.ENCRYPT_MODE, kp.getPublic(), ps); // Retrieve the key encapsulation message (from the KEM step) from // the sender. byte[] kemEncap = senderCipher.getIV(); // The HPKE recipient cipher is initialized with its own private key, // an HPKEParameterSpec using the same algorithm identifiers as used by // the sender, and the key encapsulation message from the sender. Cipher recipientCipher = Cipher.getInstance("HPKE"); HPKEParameterSpec pr = HPKEParameterSpec.of( HPKEParameterSpec.KEM_DHKEM_X25519_HKDF_SHA256, HPKEParameterSpec.KDF_HKDF_SHA256, HPKEParameterSpec.AEAD_AES_128_GCM) .withInfo(HexFormat.of().parseHex("010203040506")) .withEncapsulation(kemEncap); recipientCipher.init(Cipher.DECRYPT_MODE, kp.getPrivate(), pr); // Encryption and decryption byte[] msg = "Hello World".getBytes(StandardCharsets.UTF_8); byte[] ct = senderCipher.doFinal(msg); byte[] pt = recipientCipher.doFinal(ct); assert Arrays.equals(msg, pt);
Implementation Note
This class defines constants for some of the standard algorithm
identifiers such as KEM_DHKEM_P_256_HKDF_SHA256,
KDF_HKDF_SHA256, and AEAD_AES_128_GCM. An HPKE Cipher
implementation may support all, some, or none of the algorithm identifiers
defined here. An implementation may also support additional identifiers not
listed here, including private or experimental values.
| Modifier and Type | Field and Description |
|---|---|
| public static final int | AEAD_AES_128_GCM
AEAD algorithm identifier for AES-128-GCM as defined in RFC 9180. |
| public static final int | AEAD_AES_256_GCM
AEAD algorithm identifier for AES-256-GCM as defined in RFC 9180. |
| public static final int | AEAD_CHACHA20_POLY1305
AEAD algorithm identifier for ChaCha20Poly1305 as defined in RFC 9180. |
| private final int | |
| private final byte[] | |
| public static final int | EXPORT_ONLY
AEAD algorithm identifier for Export-only as defined in RFC 9180. |
| private final byte[] | |
| public static final int | KDF_HKDF_SHA256
KDF algorithm identifier for HKDF-SHA256 as defined in RFC 9180. |
| public static final int | KDF_HKDF_SHA384
KDF algorithm identifier for HKDF-SHA384 as defined in RFC 9180. |
| public static final int | KDF_HKDF_SHA512
KDF algorithm identifier for HKDF-SHA512 as defined in RFC 9180. |
| private final int | |
| public static final int | KEM_DHKEM_P_256_HKDF_SHA256
KEM algorithm identifier for DHKEM(P-256, HKDF-SHA256) as defined in RFC 9180. |
| public static final int | KEM_DHKEM_P_384_HKDF_SHA384
KEM algorithm identifier for DHKEM(P-384, HKDF-SHA384) as defined in RFC 9180. |
| public static final int | KEM_DHKEM_P_521_HKDF_SHA512
KEM algorithm identifier for DHKEM(P-521, HKDF-SHA512) as defined in RFC 9180. |
| public static final int | KEM_DHKEM_X25519_HKDF_SHA256
KEM algorithm identifier for DHKEM(X25519, HKDF-SHA256) as defined in RFC 9180. |
| public static final int | KEM_DHKEM_X448_HKDF_SHA512
KEM algorithm identifier for DHKEM(X448, HKDF-SHA512) as defined in RFC 9180. |
| private final int | |
| private final AsymmetricKey | |
| private final SecretKey | |
| private final byte[] |
| Access | Constructor and Description |
|---|---|
| private | HPKEParameterSpec(int kem_id, int kdf_id, int aead_id, byte[] info, SecretKey psk, byte[] psk_id, AsymmetricKey kS, byte[] encapsulation)
|
| Modifier and Type | Method and Description |
|---|---|
| public int | |
| public AsymmetricKey | Returns: the key for authentication,null if noneReturns the key for authentication, |
| private static String | |
| public byte[] | Returns: a copy of the key encapsulation message,null if noneReturns a copy of the key encapsulation message, |
| public byte[] | Returns: a copy of the application-supplied information, empty if noneReturns a copy of the application-supplied information, empty if none. |
| public int | |
| public int | |
| public static HPKEParameterSpec | Returns: a newHPKEParameterSpec objectalgorithm identifier for KEM, must be between 0 and 65535 (inclusive) kem_id, int algorithm identifier for KDF, must be between 0 and 65535 (inclusive) kdf_id, int algorithm identifier for AEAD, must be between 0 and 65535 (inclusive) aead_id)A factory method to create a new |
| public SecretKey | |
| public byte[] | Returns: a copy of the identifier for PSK, empty if noneReturns a copy of the identifier for PSK, empty if none. |
| public String | |
| public HPKEParameterSpec | Returns: a newHPKEParameterSpec objectthe authentication key kS)Creates a new |
| public HPKEParameterSpec | Returns: a newHPKEParameterSpec objectthe key encapsulation message.
The contents of the array are copied to protect against
subsequent modification. encapsulation)Creates a new |
| public HPKEParameterSpec | Returns: a newHPKEParameterSpec objectapplication-supplied information.
The contents of the array are copied to protect
against subsequent modification. info)Creates a new |
| public HPKEParameterSpec |
| AEAD_AES_128_GCM | back to summary |
|---|---|
| public static final int AEAD_AES_128_GCM AEAD algorithm identifier for AES-128-GCM as defined in RFC 9180. | |
| AEAD_AES_256_GCM | back to summary |
|---|---|
| public static final int AEAD_AES_256_GCM AEAD algorithm identifier for AES-256-GCM as defined in RFC 9180. | |
| AEAD_CHACHA20_POLY1305 | back to summary |
|---|---|
| public static final int AEAD_CHACHA20_POLY1305 AEAD algorithm identifier for ChaCha20Poly1305 as defined in RFC 9180. | |
| aead_id | back to summary |
|---|---|
| private final int aead_id | |
| encapsulation | back to summary |
|---|---|
| private final byte[] encapsulation | |
| EXPORT_ONLY | back to summary |
|---|---|
| public static final int EXPORT_ONLY AEAD algorithm identifier for Export-only as defined in RFC 9180. | |
| info | back to summary |
|---|---|
| private final byte[] info | |
| KDF_HKDF_SHA256 | back to summary |
|---|---|
| public static final int KDF_HKDF_SHA256 KDF algorithm identifier for HKDF-SHA256 as defined in RFC 9180. | |
| KDF_HKDF_SHA384 | back to summary |
|---|---|
| public static final int KDF_HKDF_SHA384 KDF algorithm identifier for HKDF-SHA384 as defined in RFC 9180. | |
| KDF_HKDF_SHA512 | back to summary |
|---|---|
| public static final int KDF_HKDF_SHA512 KDF algorithm identifier for HKDF-SHA512 as defined in RFC 9180. | |
| kdf_id | back to summary |
|---|---|
| private final int kdf_id | |
| KEM_DHKEM_P_256_HKDF_SHA256 | back to summary |
|---|---|
| public static final int KEM_DHKEM_P_256_HKDF_SHA256 KEM algorithm identifier for DHKEM(P-256, HKDF-SHA256) as defined in RFC 9180. | |
| KEM_DHKEM_P_384_HKDF_SHA384 | back to summary |
|---|---|
| public static final int KEM_DHKEM_P_384_HKDF_SHA384 KEM algorithm identifier for DHKEM(P-384, HKDF-SHA384) as defined in RFC 9180. | |
| KEM_DHKEM_P_521_HKDF_SHA512 | back to summary |
|---|---|
| public static final int KEM_DHKEM_P_521_HKDF_SHA512 KEM algorithm identifier for DHKEM(P-521, HKDF-SHA512) as defined in RFC 9180. | |
| KEM_DHKEM_X25519_HKDF_SHA256 | back to summary |
|---|---|
| public static final int KEM_DHKEM_X25519_HKDF_SHA256 KEM algorithm identifier for DHKEM(X25519, HKDF-SHA256) as defined in RFC 9180. | |
| KEM_DHKEM_X448_HKDF_SHA512 | back to summary |
|---|---|
| public static final int KEM_DHKEM_X448_HKDF_SHA512 KEM algorithm identifier for DHKEM(X448, HKDF-SHA512) as defined in RFC 9180. | |
| kem_id | back to summary |
|---|---|
| private final int kem_id | |
| kS | back to summary |
|---|---|
| private final AsymmetricKey kS | |
| psk | back to summary |
|---|---|
| private final SecretKey psk | |
| psk_id | back to summary |
|---|---|
| private final byte[] psk_id | |
| HPKEParameterSpec | back to summary |
|---|---|
| private HPKEParameterSpec(int kem_id, int kdf_id, int aead_id, byte[] info, SecretKey psk, byte[] psk_id, AsymmetricKey kS, byte[] encapsulation) | |
| aead_id | back to summary |
|---|---|
| public int aead_id() Returns the algorithm identifier for AEAD.
| |
| authKey | back to summary |
|---|---|
| public AsymmetricKey authKey() Returns the key for authentication,
| |
| bytesToString | back to summary |
|---|---|
| private static String bytesToString(byte[] input) | |
| encapsulation | back to summary |
|---|---|
| public byte[] encapsulation() Returns a copy of the key encapsulation message,
| |
| info | back to summary |
|---|---|
| public byte[] info() Returns a copy of the application-supplied information, empty if none.
| |
| kdf_id | back to summary |
|---|---|
| public int kdf_id() Returns the algorithm identifier for KDF.
| |
| kem_id | back to summary |
|---|---|
| public int kem_id() Returns the algorithm identifier for KEM.
| |
| of | back to summary |
|---|---|
| public static HPKEParameterSpec of(int kem_id, int kdf_id, int aead_id) A factory method to create a new
| |
| psk | back to summary |
|---|---|
| public SecretKey psk() Returns pre-shared key,
| |
| psk_id | back to summary |
|---|---|
| public byte[] psk_id() Returns a copy of the identifier for PSK, empty if none.
| |
| toString | back to summary |
|---|---|
| public String toString() Overrides java. Doc from java. Returns a string representation of the object.
Satisfying this method's contract implies a non-
| |
| withAuthKey | back to summary |
|---|---|
| public HPKEParameterSpec withAuthKey(AsymmetricKey kS) Creates a new Note this method does not check whether the KEM algorithm supports
| |
| withEncapsulation | back to summary |
|---|---|
| public HPKEParameterSpec withEncapsulation(byte[] encapsulation) Creates a new
| |
| withInfo | back to summary |
|---|---|
| public HPKEParameterSpec withInfo(byte[] info) Creates a new For interoperability, RFC 9180 Section 7.2.1 recommends limiting this value to a maximum of 64 bytes.
| |
| withPsk | back to summary |
|---|---|
| public HPKEParameterSpec withPsk(SecretKey psk, byte[] psk_id) Creates a new RFC 9180 Section 5.1.2 requires the PSK MUST have at least 32 bytes of entropy. For interoperability, RFC 9180 Section 7.2.1 recommends limiting the key size and identifier length to a maximum of 64 bytes.
| |