Class HPKEParameterSpec
- All Implemented Interfaces:
AlgorithmParameterSpec
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 creates an HPKEParameterSpec
instance 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 the
IANA HPKE page.
Once an HPKEParameterSpec
object is created, additional methods
are available to generate new HPKEParameterSpec
objects with
different features:
-
Application-supplied information can be provided using the
withInfo(byte[])
method by both sides. -
To authenticate using a pre-shared key (
mode_psk
), the pre-shared key and its identifier must be provided using thewithPsk(SecretKey, byte[])
method by both sides. -
To authenticate using an asymmetric key (
mode_auth
), the asymmetric keys must be provided using thewithAuthKey(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. -
To authenticate using both a PSK and an asymmetric key
(
mode_auth_psk
), bothwithAuthKey(AsymmetricKey)
andwithPsk(SecretKey, byte[])
methods must be called as described above. -
In HPKE, a shared secret is negotiated during the KEM step and a key
encapsulation message must be transmitted from the sender to the recipient
so that the recipient can recover this shared secret. On the sender side,
after the cipher is initialized, the key encapsulation message can be
retrieved using the
Cipher.getIV()
method. On the recipient side, this message must be supplied as part of anHPKEParameterSpec
object obtained from thewithEncapsulation(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 by the
init
method. The following are cases of invalid parameters:
- An algorithm identifier is unsupported or does not match the provided key type.
- The key encapsulation message is not provided on the recipient side.
- An attempt to use
withAuthKey(key)
is made with an incompatible key. - An attempt to use
withAuthKey(key)
is made butmode_auth
ormode_auth_psk
is not supported by the KEM 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("app_info".getBytes(StandardCharsets.UTF_8));
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("app_info".getBytes(StandardCharsets.UTF_8))
.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
, andAEAD_AES_128_GCM
. An HPKECipher
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. - Since:
- 26
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final int
AEAD algorithm identifier for AES-128-GCM as defined in Section 7.3 of RFC 9180.static final int
AEAD algorithm identifier for AES-256-GCM as defined in Section 7.3 of RFC 9180.static final int
AEAD algorithm identifier for ChaCha20Poly1305 as defined in Section 7.3 of RFC 9180.static final int
AEAD algorithm identifier for Export-only as defined in Section 7.3 of RFC 9180.static final int
KDF algorithm identifier for HKDF-SHA256 as defined in Section 7.2 of RFC 9180.static final int
KDF algorithm identifier for HKDF-SHA384 as defined in Section 7.2 of RFC 9180.static final int
KDF algorithm identifier for HKDF-SHA512 as defined in Section 7.2 of RFC 9180.static final int
KEM algorithm identifier for DHKEM(P-256, HKDF-SHA256) as defined in Section 7.1 of RFC 9180.static final int
KEM algorithm identifier for DHKEM(P-384, HKDF-SHA384) as defined in Section 7.1 of RFC 9180.static final int
KEM algorithm identifier for DHKEM(P-521, HKDF-SHA512) as defined in Section 7.1 of RFC 9180.static final int
KEM algorithm identifier for DHKEM(X25519, HKDF-SHA256) as defined in Section 7.1 of RFC 9180.static final int
KEM algorithm identifier for DHKEM(X448, HKDF-SHA512) as defined in Section 7.1 of RFC 9180. -
Method Summary
Modifier and TypeMethodDescriptionint
aead_id()
Returns the algorithm identifier for AEAD.authKey()
Returns the key for authentication,null
if none.byte[]
Returns a copy of the key encapsulation message,null
if none.byte[]
info()
Returns a copy of the application-supplied information, empty if none.int
kdf_id()
Returns the algorithm identifier for KDF.int
kem_id()
Returns the algorithm identifier for KEM.static HPKEParameterSpec
of
(int kem_id, int kdf_id, int aead_id) A factory method to create a newHPKEParameterSpec
object with specified KEM, KDF, and AEAD algorithm identifiers inmode_base
mode with an emptyinfo
.psk()
Returns pre-shared key,null
if none.byte[]
psk_id()
Returns a copy of the identifier for PSK, empty if none.toString()
Returns a string representation of the object.Creates a newHPKEParameterSpec
object with the specified authentication key value.withEncapsulation
(byte[] encapsulation) Creates a newHPKEParameterSpec
object with the specified key encapsulation message value that will be used by the recipient.withInfo
(byte[] info) Creates a newHPKEParameterSpec
object with the specifiedinfo
value.Creates a newHPKEParameterSpec
object with the specifiedpsk
andpsk_id
values.
-
Field Details
-
KEM_DHKEM_P_256_HKDF_SHA256
public static final int KEM_DHKEM_P_256_HKDF_SHA256KEM algorithm identifier for DHKEM(P-256, HKDF-SHA256) as defined in Section 7.1 of RFC 9180.- See Also:
-
KEM_DHKEM_P_384_HKDF_SHA384
public static final int KEM_DHKEM_P_384_HKDF_SHA384KEM algorithm identifier for DHKEM(P-384, HKDF-SHA384) as defined in Section 7.1 of RFC 9180.- See Also:
-
KEM_DHKEM_P_521_HKDF_SHA512
public static final int KEM_DHKEM_P_521_HKDF_SHA512KEM algorithm identifier for DHKEM(P-521, HKDF-SHA512) as defined in Section 7.1 of RFC 9180.- See Also:
-
KEM_DHKEM_X25519_HKDF_SHA256
public static final int KEM_DHKEM_X25519_HKDF_SHA256KEM algorithm identifier for DHKEM(X25519, HKDF-SHA256) as defined in Section 7.1 of RFC 9180.- See Also:
-
KEM_DHKEM_X448_HKDF_SHA512
public static final int KEM_DHKEM_X448_HKDF_SHA512KEM algorithm identifier for DHKEM(X448, HKDF-SHA512) as defined in Section 7.1 of RFC 9180.- See Also:
-
KDF_HKDF_SHA256
public static final int KDF_HKDF_SHA256KDF algorithm identifier for HKDF-SHA256 as defined in Section 7.2 of RFC 9180.- See Also:
-
KDF_HKDF_SHA384
public static final int KDF_HKDF_SHA384KDF algorithm identifier for HKDF-SHA384 as defined in Section 7.2 of RFC 9180.- See Also:
-
KDF_HKDF_SHA512
public static final int KDF_HKDF_SHA512KDF algorithm identifier for HKDF-SHA512 as defined in Section 7.2 of RFC 9180.- See Also:
-
AEAD_AES_128_GCM
public static final int AEAD_AES_128_GCMAEAD algorithm identifier for AES-128-GCM as defined in Section 7.3 of RFC 9180.- See Also:
-
AEAD_AES_256_GCM
public static final int AEAD_AES_256_GCMAEAD algorithm identifier for AES-256-GCM as defined in Section 7.3 of RFC 9180.- See Also:
-
AEAD_CHACHA20_POLY1305
public static final int AEAD_CHACHA20_POLY1305AEAD algorithm identifier for ChaCha20Poly1305 as defined in Section 7.3 of RFC 9180.- See Also:
-
EXPORT_ONLY
public static final int EXPORT_ONLYAEAD algorithm identifier for Export-only as defined in Section 7.3 of RFC 9180.- See Also:
-
-
Method Details
-
of
A factory method to create a newHPKEParameterSpec
object with specified KEM, KDF, and AEAD algorithm identifiers inmode_base
mode with an emptyinfo
.- Parameters:
kem_id
- algorithm identifier for KEM, must be between 0 and 65535 (inclusive)kdf_id
- algorithm identifier for KDF, must be between 0 and 65535 (inclusive)aead_id
- algorithm identifier for AEAD, must be between 0 and 65535 (inclusive)- Returns:
- a new
HPKEParameterSpec
object - Throws:
IllegalArgumentException
- if any input value is out of range (must be between 0 and 65535, inclusive).
-
withInfo
Creates a newHPKEParameterSpec
object with the specifiedinfo
value.For interoperability, RFC 9180 Section 7.2.1 recommends limiting this value to a maximum of 64 bytes.
- Parameters:
info
- application-supplied information. The contents of the array are copied to protect against subsequent modification.- Returns:
- a new
HPKEParameterSpec
object - Throws:
NullPointerException
- ifinfo
isnull
IllegalArgumentException
- ifinfo
is empty.
-
withPsk
Creates a newHPKEParameterSpec
object with the specifiedpsk
andpsk_id
values.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.
- Parameters:
psk
- pre-shared keypsk_id
- identifier for PSK. The contents of the array are copied to protect against subsequent modification.- Returns:
- a new
HPKEParameterSpec
object - Throws:
NullPointerException
- ifpsk
orpsk_id
isnull
IllegalArgumentException
- ifpsk
is shorter than 32 bytes orpsk_id
is empty
-
withEncapsulation
Creates a newHPKEParameterSpec
object with the specified key encapsulation message value that will be used by the recipient.- Parameters:
encapsulation
- the key encapsulation message. The contents of the array are copied to protect against subsequent modification.- Returns:
- a new
HPKEParameterSpec
object - Throws:
NullPointerException
- ifencapsulation
isnull
-
withAuthKey
Creates a newHPKEParameterSpec
object with the specified authentication key value.Note: this method does not check whether the KEM supports
mode_auth
ormode_auth_psk
. If the resulting object is used to initialize an HPKE cipher with an unsupported mode, anInvalidAlgorithmParameterException
will be thrown at that time.- Parameters:
kS
- the authentication key- Returns:
- a new
HPKEParameterSpec
object - Throws:
NullPointerException
- ifkS
isnull
-
kem_id
public int kem_id()Returns the algorithm identifier for KEM .- Returns:
- the algorithm identifier for KEM
-
kdf_id
public int kdf_id()Returns the algorithm identifier for KDF .- Returns:
- the algorithm identifier for KDF
-
aead_id
public int aead_id()Returns the algorithm identifier for AEAD .- Returns:
- the algorithm identifier for AEAD
-
info
public byte[] info()Returns a copy of the application-supplied information, empty if none.- Returns:
- a copy of the application-supplied information, empty if none
-
psk
-
psk_id
public byte[] psk_id()Returns a copy of the identifier for PSK, empty if none.- Returns:
- a copy of the identifier for PSK, empty if none
-
authKey
Returns the key for authentication,null
if none.- Returns:
- the key for authentication,
null
if none
-
encapsulation
public byte[] encapsulation()Returns a copy of the key encapsulation message,null
if none.- Returns:
- a copy of the key encapsulation message,
null
if none
-
toString
-