WebBuf WebBuf
Docs

Hybrid post-quantum

@webbuf/aesgcm-p256dh-mlkem

Hybrid AES-256-GCM with P-256 ECDH + ML-KEM-768: classical + post-quantum authenticated encryption

Install

npm install @webbuf/aesgcm-p256dh-mlkem

Usage

import {
  aesgcmP256dhMlkemEncrypt,
  aesgcmP256dhMlkemDecrypt,
} from "@webbuf/aesgcm-p256dh-mlkem";
import { mlKem768KeyPair } from "@webbuf/mlkem";
import { p256PublicKeyCreate } from "@webbuf/p256";
import { FixedBuf } from "@webbuf/fixedbuf";
import { WebBuf } from "@webbuf/webbuf";

// Both parties have persistent (static-static) P-256 keypairs
const senderPriv = FixedBuf.fromRandom<32>(32);
const senderPub = p256PublicKeyCreate(senderPriv);
const recipientPriv = FixedBuf.fromRandom<32>(32);
const recipientPub = p256PublicKeyCreate(recipientPriv);

// Recipient holds an ML-KEM-768 keypair too
const { encapsulationKey, decapsulationKey } = mlKem768KeyPair();

// Sender encrypts using its own P-256 priv, recipient's P-256 pub,
// recipient's ML-KEM encapsulation key
const plaintext = WebBuf.fromUtf8("hybrid encryption");
const ciphertext = aesgcmP256dhMlkemEncrypt(
  senderPriv,
  recipientPub,
  encapsulationKey,
  plaintext,
);

// Recipient decrypts using its own P-256 priv, sender's P-256 pub,
// own ML-KEM decapsulation key
const recovered = aesgcmP256dhMlkemDecrypt(
  recipientPriv,
  senderPub,
  decapsulationKey,
  ciphertext,
);

API reference (4 exports)

Constants

AESGCM_P256DH_MLKEM

const
AESGCM_P256DH_MLKEM: { readonly versionByte: 2; readonly kemCiphertextSize: 1088; readonly ivSize: 12; readonly tagSize: 16; readonly fixedOverhead: number; readonly hkdfInfo: "webbuf:aesgcm-p256dh-mlkem v1"; }

Functions

_aesgcmP256dhMlkemEncryptDeterministic

function

Test/internal-only: encrypt with caller-supplied ML-KEM `m` and AES-GCM `iv`. Used by the KAT regression tests in `test/audit.test.ts` to assert byte-precise output against the fixtures from issue 0004 (empty AAD) and issue 0006 Experiment 2 (non-empty AAD). Application code should use `aesgcmP256dhMlkemEncrypt`.

_aesgcmP256dhMlkemEncryptDeterministic(senderPrivKey: FixedBuf<32>, recipientPubKey: FixedBuf<33>, recipientEncapKey: FixedBuf<1184>, plaintext: WebBuf, m: FixedBuf<32>, iv: FixedBuf<12>, aad?: WebBuf): WebBuf

aesgcmP256dhMlkemDecrypt

function

Decrypt an `@webbuf/aesgcm-p256dh-mlkem` ciphertext. Validates the version byte and minimum length, computes the same hybrid key by combining ECDH and decapsulated KEM shared secrets, and decrypts. Throws on version-byte mismatch, truncation, or AES-GCM authentication failure (which catches tampered KEM ciphertext, tampered AES ciphertext, tampered IV, AAD mismatch, or any wrong input key — including a wrong P-256 sender pub, wrong P-256 recipient priv, or wrong ML-KEM decapsulation key).

aesgcmP256dhMlkemDecrypt(recipientPrivKey: FixedBuf<32>, senderPubKey: FixedBuf<33>, decapKey: FixedBuf<2400>, ciphertext: WebBuf, aad?: WebBuf): WebBuf

aesgcmP256dhMlkemEncrypt

function

Encrypt a message with hybrid P-256 ECDH + ML-KEM-768 key exchange. Both parties use persistent (static-static) P-256 keypairs. The sender provides their own private P-256 key and the recipient's public P-256 key plus ML-KEM-768 encapsulation key. The AES key is derived from the concatenation of the raw 32-byte ECDH X-coordinate and the 32-byte ML-KEM shared secret via HKDF-SHA-256. `aad` is optional Additional Authenticated Data — bytes that are authenticated by the AES-GCM tag but not encrypted and not transmitted in the output. The recipient must supply the same `aad` bytes the sender used; any mismatch causes `aesgcmP256dhMlkemDecrypt` to throw. Empty AAD is the default and matches the original issue 0004 behavior. Output layout: [0..1) version byte (0x02) [1..1089) ML-KEM-768 ciphertext (1088 bytes) [1089..1101) AES-GCM IV (12 bytes) [1101..1101+N) AES-GCM ciphertext (N bytes; same length as plaintext) [1101+N..1117+N) AES-GCM authentication tag (16 bytes)

aesgcmP256dhMlkemEncrypt(senderPrivKey: FixedBuf<32>, recipientPubKey: FixedBuf<33>, recipientEncapKey: FixedBuf<1184>, plaintext: WebBuf, aad?: WebBuf): WebBuf