HPKE (Hybrid Public Key Encryption, RFC 9180)
pki.hpke.setupS
pki.hpke.setupS(suiteIds, recipientPublicKey, opts?) -> { enc, context, sharedSecret }
Establish a sender HPKE context for a recipient KEM public key: encapsulate a shared secret and run the key schedule, returning the encapsulated key enc (send it to the recipient) and a context whose .seal(aad, pt) / .export(ctx, L) encrypt and derive further secrets. suiteIds is { kem, kdf, aead } from pki.hpke.suites; recipientPublicKey is a node KeyObject or the serialized public key bytes (the uncompressed point, the raw Montgomery coordinate, or the ML-KEM encapsulation key). opts.mode selects base / psk / auth / auth-psk (default base); opts.info, opts.psk/opts.pskId, and opts.senderKey (auth modes) supply the corresponding inputs; an option that belongs to another mode, such as senderKey in base mode, is refused with hpke/bad-input rather than left unused. The auth modes exist for the DHKEM suites only: an ML-KEM suite throws hpke/auth-unsupported.
Example
var s = pki.hpke.suites, ids = { kem: s.KEM.DHKEM_X25519_HKDF_SHA256, kdf: s.KDF.HKDF_SHA256, aead: s.AEAD.AES_128_GCM };
var pkR = Buffer.from("8c7781768956b9dd38997c5a83ab5b9315270a9f73d87d676573c5bca74e3e48", "hex");
var sender = pki.hpke.setupS(ids, pkR, { info: Buffer.from("app") });
var ct = sender.context.seal(Buffer.from("aad"), Buffer.from("secret"));
References
- spec RFC 9180
pki.hpke.setupR
pki.hpke.setupR(suiteIds, enc, recipientPrivateKey, opts?) -> context
Establish the recipient HPKE context from the sender's encapsulated key enc and the recipient KEM private key, recovering the same shared secret and key schedule. The private key is a node KeyObject, or { skm, pkm } where skm is the raw private scalar of a DHKEM suite or the 64-byte seed of an ML-KEM suite; pkm is optional, and when given it must be the public key derived from skm or the call throws hpke/bad-key. The returned context .open(aad, ct) decrypts and .export(ctx, L) derives secrets. opts mirrors setupS (mode / info / psk / pskId), with opts.senderPublicKey for the auth modes (DHKEM suites only). A ciphertext whose tag does not verify throws hpke/open-failed.
Example
var s = pki.hpke.suites, ids = { kem: s.KEM.DHKEM_X25519_HKDF_SHA256, kdf: s.KDF.HKDF_SHA256, aead: s.AEAD.AES_128_GCM };
var pkR = Buffer.from("8c7781768956b9dd38997c5a83ab5b9315270a9f73d87d676573c5bca74e3e48", "hex");
var skR = Buffer.from("009f2181fba5f8908632c10ea1137c40a849728fde016c4602458b943a5dc048", "hex");
var sender = pki.hpke.setupS(ids, pkR);
var recipient = pki.hpke.setupR(ids, sender.enc, { skm: skR, pkm: pkR });
var pt = recipient.open(Buffer.alloc(0), sender.context.seal(Buffer.alloc(0), Buffer.from("hi")));
References
- spec RFC 9180
pki.hpke.seal
pki.hpke.seal(suiteIds, recipientPublicKey, opts, aad, pt) -> { enc, ct }
Single-shot HPKE encryption (RFC 9180 sec. 6): set up a sender context and encrypt one plaintext, returning the encapsulated key enc and ciphertext ct. Equivalent to setupS followed by one context.seal. opts is the setupS options object (mode / info / psk / senderKey).
Example
// requires: mlKemPkR -- the recipient's ML-KEM-768 encapsulation key (1184 bytes)
var s = pki.hpke.suites, ids = { kem: s.KEM.ML_KEM_768, kdf: s.KDF.HKDF_SHA256, aead: s.AEAD.AES_256_GCM };
var out = pki.hpke.seal(ids, mlKemPkR, {}, Buffer.from("aad"), Buffer.from("msg"));
References
- spec RFC 9180
pki.hpke.open
pki.hpke.open(suiteIds, enc, recipientPrivateKey, opts, aad, ct) -> pt
Single-shot HPKE decryption (RFC 9180 sec. 6): set up a recipient context from enc and decrypt one ciphertext, returning the plaintext. A tag that does not verify throws hpke/open-failed and returns no plaintext.
Example
// requires: mlKemPkR -- the recipient's ML-KEM-768 encapsulation key (1184 bytes)
// requires: mlKemSkR -- { skm } holding the recipient's 64-byte ML-KEM-768 seed
var s = pki.hpke.suites, ids = { kem: s.KEM.ML_KEM_768, kdf: s.KDF.HKDF_SHA256, aead: s.AEAD.AES_256_GCM };
var o = pki.hpke.seal(ids, mlKemPkR, {}, Buffer.alloc(0), Buffer.from("m"));
var pt = pki.hpke.open(ids, o.enc, mlKemSkR, {}, Buffer.alloc(0), o.ct);
References
- spec RFC 9180