@cardanowall/sdk-ts 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/client/index.cjs +1140 -363
  2. package/dist/client/index.cjs.map +1 -1
  3. package/dist/client/index.d.cts +42 -5
  4. package/dist/client/index.d.ts +42 -5
  5. package/dist/client/index.js +1138 -365
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/conformance/cli.cjs +4400 -2121
  8. package/dist/conformance/cli.cjs.map +1 -1
  9. package/dist/conformance/cli.js +4401 -2122
  10. package/dist/conformance/cli.js.map +1 -1
  11. package/dist/fetch/index.cjs +33 -14
  12. package/dist/fetch/index.cjs.map +1 -1
  13. package/dist/fetch/index.d.cts +2 -2
  14. package/dist/fetch/index.d.ts +2 -2
  15. package/dist/fetch/index.js +32 -15
  16. package/dist/fetch/index.js.map +1 -1
  17. package/dist/{fetch-outbound-BT5-NiYN.d.cts → fetch-outbound-dOK3ZxYa.d.cts} +7 -3
  18. package/dist/{fetch-outbound-BT5-NiYN.d.ts → fetch-outbound-dOK3ZxYa.d.ts} +7 -3
  19. package/dist/hash/index.cjs +1 -1
  20. package/dist/hash/index.cjs.map +1 -1
  21. package/dist/hash/index.js +1 -1
  22. package/dist/hash/index.js.map +1 -1
  23. package/dist/identity/index.cjs +356 -230
  24. package/dist/identity/index.cjs.map +1 -1
  25. package/dist/identity/index.d.cts +3 -2
  26. package/dist/identity/index.d.ts +3 -2
  27. package/dist/identity/index.js +356 -230
  28. package/dist/identity/index.js.map +1 -1
  29. package/dist/index.cjs +5474 -2518
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +7 -7
  32. package/dist/index.d.ts +7 -7
  33. package/dist/index.js +5454 -2514
  34. package/dist/index.js.map +1 -1
  35. package/dist/merkle/index.cjs +1 -1
  36. package/dist/merkle/index.js +1 -1
  37. package/dist/types-Cexm4VH9.d.cts +119 -0
  38. package/dist/types-CgoBub9J.d.ts +119 -0
  39. package/dist/{types-DGsZTMuZ.d.cts → types-Dp4wUSFI.d.cts} +220 -1
  40. package/dist/{types-DGsZTMuZ.d.ts → types-Dp4wUSFI.d.ts} +220 -1
  41. package/dist/verifier/index.cjs +4419 -2147
  42. package/dist/verifier/index.cjs.map +1 -1
  43. package/dist/verifier/index.d.cts +159 -111
  44. package/dist/verifier/index.d.ts +159 -111
  45. package/dist/verifier/index.js +4407 -2143
  46. package/dist/verifier/index.js.map +1 -1
  47. package/package.json +3 -3
  48. package/dist/types-B8Q3gW54.d.ts +0 -123
  49. package/dist/types-CLXdbjqr.d.cts +0 -123
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/utils.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/_crystals.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/ml-kem.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/hybrid.ts","../../../crypto-core/src/kdf/hkdf.ts","../../../crypto-core/src/kem/mlkem768x25519.ts","../../../crypto-core/src/kem/x25519.ts","../../../crypto-core/src/sig/ed25519.ts","../../../crypto-core/src/seed-derive/errors.ts","../../../crypto-core/src/seed-derive/derive.ts","../../../crypto-core/src/recipient/bech32.ts","../../../crypto-core/src/recipient/age-recipient.ts","../../../crypto-core/src/aead/errors.ts","../../../crypto-core/src/aead/chacha20-poly1305.ts","../../../crypto-core/src/aead/xchacha20-poly1305.ts","../../../crypto-core/src/sealed-poe/errors.ts","../../../crypto-core/src/sealed-poe/slots-codec.ts","../../../crypto-core/src/cbor/canonical.ts","../../../crypto-core/src/sealed-poe/transcript.ts","../../../crypto-core/src/sealed-poe/wrap.ts","../../../crypto-core/src/util/compare-ct.ts","../../../crypto-core/src/sealed-poe/unwrap.ts","../../src/identity/seed-identity.ts"],"names":["abytes","randb","abytes_","opts","N","Q","F","ROOT_OF_UNITY","reverseBits","FFTCore","shake128","u32","swap32IfBE","shake256","sha3_256","sha3_512","bytesToNumberLE","bytesToNumberBE","anumber","x25519","concatBytes","asciiToBytes","hkdf","sha256","ed","sha512","chacha20poly1305","xchacha20poly1305","hkdfSha256","MLKEM768X25519_SEED_LENGTH","mlkem768x25519Keygen","x25519PublicKey","encode","sortCoreDeterministic","ZERO_NONCE_12","EMPTY_SALT","X25519_SECRET_KEY_LENGTH","X25519_PUBLIC_KEY_LENGTH","NONCE_LENGTH","WRAP_LENGTH","SLOTS_MAC_LENGTH","concat","hmac","ed2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Utilities for hex, bytearray and number handling.\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport {\n type CHash,\n type TypedArray,\n abytes,\n abytes as abytes_,\n concatBytes,\n isLE,\n randomBytes as randb,\n} from '@noble/hashes/utils.js';\n/**\n * Bytes API type helpers for old + new TypeScript.\n *\n * TS 5.6 has `Uint8Array`, while TS 5.9+ made it generic `Uint8Array<ArrayBuffer>`.\n * We can't use specific return type, because TS 5.6 will error.\n * We can't use generic return type, because most TS 5.9 software will expect specific type.\n *\n * Maps typed-array input leaves to broad forms.\n * These are compatibility adapters, not ownership guarantees.\n *\n * - `TArg` keeps byte inputs broad.\n * - `TRet` marks byte outputs for TS 5.6 and TS 5.9+ compatibility.\n */\nexport type TypedArg<T> = T extends BigInt64Array\n ? BigInt64Array\n : T extends BigUint64Array\n ? BigUint64Array\n : T extends Float32Array\n ? Float32Array\n : T extends Float64Array\n ? Float64Array\n : T extends Int16Array\n ? Int16Array\n : T extends Int32Array\n ? Int32Array\n : T extends Int8Array\n ? Int8Array\n : T extends Uint16Array\n ? Uint16Array\n : T extends Uint32Array\n ? Uint32Array\n : T extends Uint8ClampedArray\n ? Uint8ClampedArray\n : T extends Uint8Array\n ? Uint8Array\n : never;\n/** Maps typed-array output leaves to narrow TS-compatible forms. */\nexport type TypedRet<T> = T extends BigInt64Array\n ? ReturnType<typeof BigInt64Array.of>\n : T extends BigUint64Array\n ? ReturnType<typeof BigUint64Array.of>\n : T extends Float32Array\n ? ReturnType<typeof Float32Array.of>\n : T extends Float64Array\n ? ReturnType<typeof Float64Array.of>\n : T extends Int16Array\n ? ReturnType<typeof Int16Array.of>\n : T extends Int32Array\n ? ReturnType<typeof Int32Array.of>\n : T extends Int8Array\n ? ReturnType<typeof Int8Array.of>\n : T extends Uint16Array\n ? ReturnType<typeof Uint16Array.of>\n : T extends Uint32Array\n ? ReturnType<typeof Uint32Array.of>\n : T extends Uint8ClampedArray\n ? ReturnType<typeof Uint8ClampedArray.of>\n : T extends Uint8Array\n ? ReturnType<typeof Uint8Array.of>\n : never;\n/** Recursively adapts byte-carrying API input types. See {@link TypedArg}. */\nexport type TArg<T> =\n | T\n | ([TypedArg<T>] extends [never]\n ? T extends (...args: infer A) => infer R\n ? ((...args: { [K in keyof A]: TRet<A[K]> }) => TArg<R>) & {\n [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TArg<T[K]>;\n }\n : T extends [infer A, ...infer R]\n ? [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]\n : T extends readonly [infer A, ...infer R]\n ? readonly [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]\n : T extends (infer A)[]\n ? TArg<A>[]\n : T extends readonly (infer A)[]\n ? readonly TArg<A>[]\n : T extends Promise<infer A>\n ? Promise<TArg<A>>\n : T extends object\n ? { [K in keyof T]: TArg<T[K]> }\n : T\n : TypedArg<T>);\n/** Recursively adapts byte-carrying API output types. See {@link TypedArg}. */\nexport type TRet<T> = T extends unknown\n ? T &\n ([TypedRet<T>] extends [never]\n ? T extends (...args: infer A) => infer R\n ? ((...args: { [K in keyof A]: TArg<A[K]> }) => TRet<R>) & {\n [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TRet<T[K]>;\n }\n : T extends [infer A, ...infer R]\n ? [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]\n : T extends readonly [infer A, ...infer R]\n ? readonly [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]\n : T extends (infer A)[]\n ? TRet<A>[]\n : T extends readonly (infer A)[]\n ? readonly TRet<A>[]\n : T extends Promise<infer A>\n ? Promise<TRet<A>>\n : T extends object\n ? { [K in keyof T]: TRet<T[K]> }\n : T\n : TypedRet<T>)\n : never;\n/**\n * Asserts that a value is a byte array and optionally checks its length.\n * Returns the original reference unchanged on success, and currently also accepts Node `Buffer`\n * values through the upstream validator.\n * This helper throws on malformed input, so APIs that must return `false` need to guard lengths\n * before decoding or before calling it.\n * @example\n * Validate that a value is a byte array with the expected length.\n * ```ts\n * abytes(new Uint8Array([1]), 1);\n * ```\n */\nconst abytesDoc: typeof abytes = abytes;\nexport { abytesDoc as abytes };\n/**\n * Concatenates byte arrays into a new `Uint8Array`.\n * Zero arguments return an empty `Uint8Array`.\n * Invalid segments throw before allocation because each argument is validated first.\n * @example\n * Concatenate two byte arrays into one result.\n * ```ts\n * concatBytes(new Uint8Array([1]), new Uint8Array([2]));\n * ```\n */\nconst concatBytesDoc: typeof concatBytes = concatBytes;\nexport { concatBytesDoc as concatBytes };\n/**\n * Returns cryptographically secure random bytes.\n * Requires `globalThis.crypto.getRandomValues` and throws if that API is unavailable.\n * `bytesLength` is validated by the upstream helper as a non-negative integer before allocation,\n * so negative and fractional values both throw instead of truncating through JS `ToIndex`.\n * @param bytesLength - Number of random bytes to generate.\n * @returns Fresh random bytes.\n * @example\n * Generate a fresh random seed.\n * ```ts\n * const seed = randomBytes(4);\n * ```\n */\nexport const randomBytes: typeof randb = randb;\n\n/**\n * Compares two byte arrays in a length-constant way for equal lengths.\n * Unequal lengths return `false` immediately, and there is no runtime type validation.\n * @param a - First byte array.\n * @param b - Second byte array.\n * @returns Whether both arrays contain the same bytes.\n * @example\n * Compare two byte arrays for equality.\n * ```ts\n * equalBytes(new Uint8Array([1]), new Uint8Array([1]));\n * ```\n */\nexport function equalBytes(a: TArg<Uint8Array>, b: TArg<Uint8Array>): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n\n/**\n * Copies bytes into a fresh `Uint8Array`.\n * Returns a detached plain `Uint8Array` after validating that the input is real bytes.\n * @param bytes - Source bytes.\n * @returns Copy of the input bytes.\n * @example\n * Copy bytes into a fresh array.\n * ```ts\n * copyBytes(new Uint8Array([1, 2]));\n * ```\n */\nexport function copyBytes(bytes: TArg<Uint8Array>): TRet<Uint8Array> {\n // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict\n // because callers use it at byte-validation boundaries before mutating the detached copy.\n return Uint8Array.from(abytes(bytes)) as TRet<Uint8Array>;\n}\n\n/**\n * Byte-swaps each 64-bit lane in place.\n * Falcon's exact binary64 tables are stored as little-endian byte payloads, so BE runtimes need\n * this boundary helper before aliasing them as host `Float64Array` lanes.\n * @param arr - Byte buffer whose length is a multiple of 8.\n * @returns The same buffer after in-place 64-bit lane byte swaps.\n * @example\n * Byte-swap one 64-bit lane in place.\n * ```ts\n * byteSwap64(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]));\n * ```\n */\nexport function byteSwap64<T extends ArrayBufferView>(arr: T): T {\n const bytes = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n for (let i = 0; i < bytes.length; i += 8) {\n const a0 = bytes[i + 0];\n const a1 = bytes[i + 1];\n const a2 = bytes[i + 2];\n const a3 = bytes[i + 3];\n bytes[i + 0] = bytes[i + 7];\n bytes[i + 1] = bytes[i + 6];\n bytes[i + 2] = bytes[i + 5];\n bytes[i + 3] = bytes[i + 4];\n bytes[i + 4] = a3;\n bytes[i + 5] = a2;\n bytes[i + 6] = a1;\n bytes[i + 7] = a0;\n }\n return arr;\n}\n/**\n * Byte-swaps 64-bit lanes on big-endian runtimes and returns the input unchanged on little-endian.\n * This keeps Falcon's binary64 tables in canonical little-endian order before aliasing them as\n * `Float64Array` lanes on the current host.\n * @param arr - Buffer to pass through or swap in place.\n * @returns The same buffer, normalized for Falcon's little-endian table layout.\n * @example\n * Normalize one host-endian buffer for Falcon's float tables.\n * ```ts\n * baswap64If(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]));\n * ```\n */\nexport const baswap64If: <T extends ArrayBufferView>(arr: T) => T = isLE\n ? (arr) => arr\n : byteSwap64;\n\n/** Shared key-generation surface for signers and KEMs. */\nexport type CryptoKeys = {\n /** Optional metadata about the algorithm family or variant. */\n info?: { type?: string };\n /** Public byte lengths for the exported key material. */\n lengths: { seed?: number; publicKey?: number; secretKey?: number };\n /**\n * Generate one secret/public keypair.\n * @param seed - Optional seed bytes for deterministic key generation.\n * @returns Fresh secret/public keypair.\n */\n keygen: (seed?: TArg<Uint8Array>) => {\n secretKey: TRet<Uint8Array>;\n publicKey: TRet<Uint8Array>;\n };\n /**\n * Derive one public key from a secret key.\n * @param secretKey - Secret key bytes.\n * @returns Public key bytes.\n */\n getPublicKey: (secretKey: TArg<Uint8Array>) => TRet<Uint8Array>;\n};\n\n/** Verification options shared by the signature APIs. */\nexport type VerOpts = {\n /** Optional application-defined context string. */\n context?: Uint8Array;\n};\n/** Signing options shared by the signature APIs. */\nexport type SigOpts = VerOpts & {\n // Compatibility with @noble/curves: false to disable, enabled by default, user can pass U8A\n /** Optional extra entropy or `false` to disable randomized signing. */\n extraEntropy?: Uint8Array | false;\n};\n\n/**\n * Validates that an options bag is a plain object.\n * @param opts - Options object to validate.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate that an options bag is a plain object.\n * ```ts\n * validateOpts({});\n * ```\n */\nexport function validateOpts(opts: object): void {\n // Arrays silently passed here before, but these call sites expect named option-bag fields.\n if (Object.prototype.toString.call(opts) !== '[object Object]')\n throw new TypeError('expected valid options object');\n}\n\n/**\n * Validates common verification options.\n * `context` itself is validated with `abytes(...)`, and individual algorithms may narrow support\n * further after this shared plain-object gate.\n * @param opts - Verification options. See {@link VerOpts}.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate common verification options.\n * ```ts\n * validateVerOpts({ context: new Uint8Array([1]) });\n * ```\n */\nexport function validateVerOpts(opts: TArg<VerOpts>): void {\n validateOpts(opts);\n if (opts.context !== undefined) abytes(opts.context, undefined, 'opts.context');\n}\n\n/**\n * Validates common signing options.\n * `extraEntropy` is validated with `abytes(...)`; exact lengths and extra algorithm-specific\n * restrictions are enforced later by callers.\n * @param opts - Signing options. See {@link SigOpts}.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate common signing options.\n * ```ts\n * validateSigOpts({ extraEntropy: new Uint8Array([1]) });\n * ```\n */\nexport function validateSigOpts(opts: TArg<SigOpts>): void {\n validateVerOpts(opts);\n if (opts.extraEntropy !== false && opts.extraEntropy !== undefined)\n abytes(opts.extraEntropy, undefined, 'opts.extraEntropy');\n}\n\n/** Generic signature interface with key generation, signing, and verification. */\nexport type Signer = CryptoKeys & {\n /** Public byte lengths for signatures and signing randomness. */\n lengths: { signRand?: number; signature?: number };\n /**\n * Sign one message.\n * @param msg - Message bytes to sign.\n * @param secretKey - Secret key bytes.\n * @param opts - Optional signing options.\n * @returns Signature bytes.\n */\n sign: (\n msg: TArg<Uint8Array>,\n secretKey: TArg<Uint8Array>,\n opts?: TArg<SigOpts>\n ) => TRet<Uint8Array>;\n /**\n * Verify one signature.\n * @param sig - Signature bytes.\n * @param msg - Signed message bytes.\n * @param publicKey - Public key bytes.\n * @param opts - Optional verification options.\n * @returns `true` when the signature is valid, `false` when all inputs are well-formed but the\n * signature check does not pass. Some implementations also treat malformed signature encodings as\n * a verification failure and return `false`.\n * @throws On malformed API arguments or unsupported verification options.\n */\n verify: (\n sig: TArg<Uint8Array>,\n msg: TArg<Uint8Array>,\n publicKey: TArg<Uint8Array>,\n opts?: TArg<VerOpts>\n ) => boolean;\n};\n\n/** Generic key encapsulation mechanism interface. */\nexport type KEM = CryptoKeys & {\n /** Public byte lengths for ciphertexts and optional message randomness. */\n lengths: { cipherText?: number; msg?: number; msgRand?: number };\n /**\n * Encapsulate one shared secret to a recipient public key.\n * @param publicKey - Recipient public key bytes.\n * @param msg - Optional caller-provided randomness/message seed.\n * @returns Ciphertext plus shared secret.\n */\n encapsulate: (\n publicKey: TArg<Uint8Array>,\n msg?: TArg<Uint8Array>\n ) => {\n cipherText: TRet<Uint8Array>;\n sharedSecret: TRet<Uint8Array>;\n };\n /**\n * Recover the shared secret from a ciphertext and recipient secret key.\n * @param cipherText - Ciphertext bytes.\n * @param secretKey - Recipient secret key bytes.\n * @returns Decapsulated shared secret.\n */\n decapsulate: (cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) => TRet<Uint8Array>;\n};\n\n/** Bidirectional encoder/decoder interface. */\nexport interface Coder<F, T> {\n /**\n * Serialize one value.\n * @param from - Value to encode.\n * @returns Encoded representation.\n */\n encode(from: F): T;\n /**\n * Parse one serialized value.\n * @param to - Encoded representation.\n * @returns Decoded value.\n */\n decode(to: T): F;\n}\n\n/** Encoder/decoder interface specialized for byte arrays. */\nexport interface BytesCoder<T> extends Coder<T, Uint8Array> {\n /**\n * Serialize one value into bytes.\n * @param data - Value to encode.\n * @returns Encoded bytes.\n */\n encode: (data: T) => Uint8Array;\n /**\n * Parse one byte array into a value.\n * @param bytes - Encoded bytes.\n * @returns Decoded value.\n */\n decode: (bytes: Uint8Array) => T;\n}\n\n/** Fixed-length byte encoder/decoder. */\nexport type BytesCoderLen<T> = BytesCoder<T> & { bytesLen: number };\n\n// nano-packed, because struct encoding is hard.\ntype UnCoder<T> = T extends BytesCoder<infer U> ? U : never;\ntype SplitOut<T extends (number | BytesCoderLen<any>)[]> = {\n [K in keyof T]: T[K] extends number ? Uint8Array : UnCoder<T[K]>;\n};\n/**\n * Builds a fixed-layout coder from byte lengths and nested coders.\n * Raw-length fields decode as zero-copy `subarray(...)` views, and nested coders may preserve that\n * aliasing too. Nested coder `encode(...)` results are treated as owned scratch: `splitCoder`\n * copies them into the output and then zeroizes them with `fill(0)`. If a nested encoder forwards\n * caller-owned bytes, it must do so only after detaching them into a disposable copy.\n * @param label - Label used in validation errors.\n * @param lengths - Field lengths or nested coders.\n * @returns Composite fixed-length coder.\n * @example\n * Build a fixed-layout coder from byte lengths and nested coders.\n * ```ts\n * splitCoder('demo', 1, 2).encode([new Uint8Array([1]), new Uint8Array([2, 3])]);\n * ```\n */\nexport function splitCoder<T extends (number | BytesCoderLen<any>)[]>(\n label: string,\n ...lengths: T\n): TRet<BytesCoder<SplitOut<T>> & { bytesLen: number }> {\n const getLength = (c: TArg<number | BytesCoderLen<any>>) =>\n typeof c === 'number' ? c : (c as BytesCoderLen<any>).bytesLen;\n const bytesLen: number = lengths.reduce((sum: number, a) => sum + getLength(a), 0);\n return {\n bytesLen,\n encode: (bufs: T) => {\n const res = new Uint8Array(bytesLen);\n for (let i = 0, pos = 0; i < lengths.length; i++) {\n const c = lengths[i];\n const l = getLength(c);\n const b: Uint8Array = typeof c === 'number' ? (bufs[i] as any) : c.encode(bufs[i]);\n abytes_(b, l, label);\n res.set(b, pos);\n if (typeof c !== 'number') b.fill(0); // clean\n pos += l;\n }\n return res;\n },\n decode: (buf: TArg<Uint8Array>) => {\n abytes_(buf, bytesLen, label);\n const res = [];\n for (const c of lengths) {\n const l = getLength(c);\n const b = buf.subarray(0, l);\n res.push(typeof c === 'number' ? b : c.decode(b));\n buf = buf.subarray(l);\n }\n return res as SplitOut<T>;\n },\n } as any;\n}\n// nano-packed.array (fixed size)\n/**\n * Builds a fixed-length vector coder from another fixed-length coder.\n * Element decoding receives `subarray(...)` views, so aliasing depends on the element coder.\n * Element coder `encode(...)` results are treated as owned scratch: `vecCoder` copies them into\n * the output and then zeroizes them with `fill(0)`. If an element encoder forwards caller-owned\n * bytes, it must do so only after detaching them into a disposable copy. `vecCoder` also trusts\n * the `BytesCoderLen` contract: each encoded element must already be exactly `c.bytesLen` bytes.\n * @param c - Element coder.\n * @param vecLen - Number of elements in the vector.\n * @returns Fixed-length vector coder.\n * @example\n * Build a fixed-length vector coder from another fixed-length coder.\n * ```ts\n * vecCoder(\n * { bytesLen: 1, encode: (n: number) => Uint8Array.of(n), decode: (b: Uint8Array) => b[0] || 0 },\n * 2\n * ).encode([1, 2]);\n * ```\n */\nexport function vecCoder<T>(c: TArg<BytesCoderLen<T>>, vecLen: number): TRet<BytesCoderLen<T[]>> {\n const coder = c as BytesCoderLen<T>;\n const bytesLen = vecLen * coder.bytesLen;\n return {\n bytesLen,\n encode: (u: TArg<T[]>): TRet<Uint8Array> => {\n if (u.length !== vecLen)\n throw new RangeError(`vecCoder.encode: wrong length=${u.length}. Expected: ${vecLen}`);\n const res = new Uint8Array(bytesLen);\n for (let i = 0, pos = 0; i < u.length; i++) {\n const b = coder.encode(u[i] as T);\n res.set(b, pos);\n b.fill(0); // clean\n pos += b.length;\n }\n return res as TRet<Uint8Array>;\n },\n decode: (a: TArg<Uint8Array>): TRet<T[]> => {\n abytes_(a, bytesLen);\n const r: T[] = [];\n for (let i = 0; i < a.length; i += coder.bytesLen)\n r.push(coder.decode(a.subarray(i, i + coder.bytesLen)));\n return r as TRet<T[]>;\n },\n } as any;\n}\n\n/**\n * Overwrites supported typed-array inputs with zeroes in place.\n * Accepts direct typed arrays and one-level arrays of them.\n * @param list - Typed arrays or one-level lists of typed arrays to clear.\n * @example\n * Overwrite typed arrays with zeroes.\n * ```ts\n * const buf = Uint8Array.of(1, 2, 3);\n * cleanBytes(buf);\n * ```\n */\nexport function cleanBytes(...list: (TypedArray | TypedArray[])[]): void {\n for (const t of list) {\n if (Array.isArray(t)) for (const b of t) b.fill(0);\n else t.fill(0);\n }\n}\n\n/**\n * Creates a 32-bit mask with the lowest `bits` bits set.\n * @param bits - Number of low bits to keep.\n * @returns Bit mask with `bits` ones.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Create a low-bit mask for packed-field operations.\n * ```ts\n * const mask = getMask(4);\n * ```\n */\nexport function getMask(bits: number): number {\n if (!Number.isSafeInteger(bits) || bits < 0 || bits > 32)\n throw new RangeError(`expected bits in [0..32], got ${bits}`);\n // JS shifts are modulo 32, so bit 32 needs an explicit full-width mask.\n return bits === 32 ? 0xffffffff : ~(-1 << bits) >>> 0;\n}\n\n/** Shared empty byte array used as the default context. */\nexport const EMPTY: TRet<Uint8Array> = /* @__PURE__ */ Uint8Array.of();\n\n/**\n * Builds the domain-separated message payload for the pure sign/verify paths.\n * Context length `255` is valid; only `ctx.length > 255` is rejected.\n * @param msg - Message bytes.\n * @param ctx - Optional context bytes.\n * @returns Domain-separated message payload.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Build the domain-separated payload before direct signing.\n * ```ts\n * const payload = getMessage(new Uint8Array([1, 2]));\n * ```\n */\nexport function getMessage(msg: TArg<Uint8Array>, ctx: TArg<Uint8Array> = EMPTY): TRet<Uint8Array> {\n abytes_(msg);\n abytes_(ctx);\n if (ctx.length > 255) throw new RangeError('context should be 255 bytes or less');\n return concatBytes(new Uint8Array([0, ctx.length]), ctx, msg);\n}\n\n// DER tag+length plus the shared NIST hash OID arc 2.16.840.1.101.3.4.2.* used by the\n// FIPS 204 / FIPS 205 pre-hash wrappers; the final byte selects SHA-256, SHA-512, SHAKE128,\n// SHAKE256, or another approved hash/XOF under that subtree.\n// 06 09 60 86 48 01 65 03 04 02\nconst oidNistP = /* @__PURE__ */ Uint8Array.from([6, 9, 0x60, 0x86, 0x48, 1, 0x65, 3, 4, 2]);\n\n/**\n * Validates that a hash exposes a NIST hash OID and enough collision resistance.\n * Current accepted surface is broader than the FIPS algorithm tables: any hash/XOF under the NIST\n * `2.16.840.1.101.3.4.2.*` subtree is accepted if its effective `outputLen` is strong enough.\n * XOF callers must pass a callable whose `outputLen` matches the digest length they actually intend\n * to sign; bare `shake128` / `shake256` defaults are too short for the stronger prehash modes.\n * @param hash - Hash function to validate.\n * @param requiredStrength - Minimum required collision-resistance strength in bits.\n * @throws If the hash metadata or collision resistance is insufficient. {@link Error}\n * @example\n * Validate that a hash exposes a NIST hash OID and enough collision resistance.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { checkHash } from '@noble/post-quantum/utils.js';\n * checkHash(sha256, 128);\n * ```\n */\nexport function checkHash(hash: CHash, requiredStrength: number = 0): void {\n if (!hash.oid || !equalBytes(hash.oid.subarray(0, 10), oidNistP))\n throw new Error('hash.oid is invalid: expected NIST hash');\n // FIPS 204 / FIPS 205 require both collision and second-preimage strength; for approved NIST\n // hashes/XOFs under this OID subtree, the collision bound from the configured digest length is\n // the tighter runtime check, so enforce that lower bound here.\n const collisionResistance = (hash.outputLen * 8) / 2;\n if (requiredStrength > collisionResistance) {\n throw new Error(\n 'Pre-hash security strength too low: ' +\n collisionResistance +\n ', required: ' +\n requiredStrength\n );\n }\n}\n\n/**\n * Builds the domain-separated prehash payload for the prehash sign/verify paths.\n * Callers are expected to vet `hash.oid` first, e.g. via `checkHash(...)`; calling this helper\n * directly with a hash object that lacks `oid` currently throws later inside `concatBytes(...)`.\n * Context length `255` is valid; only `ctx.length > 255` is rejected.\n * @param hash - Prehash function.\n * @param msg - Message bytes.\n * @param ctx - Optional context bytes.\n * @returns Domain-separated prehash payload.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Build the domain-separated prehash payload for external hashing.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { getMessagePrehash } from '@noble/post-quantum/utils.js';\n * getMessagePrehash(sha256, new Uint8Array([1, 2]));\n * ```\n */\nexport function getMessagePrehash(\n hash: CHash,\n msg: TArg<Uint8Array>,\n ctx: TArg<Uint8Array> = EMPTY\n): TRet<Uint8Array> {\n abytes_(msg);\n abytes_(ctx);\n if (ctx.length > 255) throw new RangeError('context should be 255 bytes or less');\n const hashed = hash(msg);\n return concatBytes(new Uint8Array([1, ctx.length]), ctx, hash.oid!, hashed);\n}\n","/**\n * Internal methods for lattice-based ML-KEM and ML-DSA.\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { FFTCore, reverseBits } from '@noble/curves/abstract/fft.js';\nimport { shake128, shake256 } from '@noble/hashes/sha3.js';\nimport type { TypedArray } from '@noble/hashes/utils.js';\nimport {\n type BytesCoderLen,\n cleanBytes,\n type Coder,\n getMask,\n type TArg,\n type TRet,\n} from './utils.ts';\n\n/** Extendable-output reader used by the CRYSTALS implementations. */\nexport type XOF = (\n seed: Uint8Array,\n blockLen?: number\n) => {\n /**\n * Read diagnostic counters for the current XOF session.\n * @returns Current call and XOF block counters.\n */\n stats: () => { calls: number; xofs: number };\n /**\n * Select one `(x, y)` coordinate pair and get a block reader for it.\n * Only one coordinate stream is live at a time: a later `get(...)` call rebinds the shared\n * SHAKE state and invalidates older readers.\n * Each squeeze aliases one mutable internal output buffer, so callers must copy blocks they\n * want to retain before the next read.\n * @param x - First matrix coordinate.\n * @param y - Second matrix coordinate.\n * @returns Lazy block reader for that coordinate pair.\n */\n get: (x: number, y: number) => () => Uint8Array; // return block aligned to blockLen and 3\n /** Wipe any buffered state once the reader is no longer needed. */\n clean: () => void;\n};\n\n/** CRYSTALS (ml-kem, ml-dsa) options */\n/** Shared polynomial and NTT parameters for CRYSTALS algorithms. */\nexport type CrystalOpts<T extends TypedArray> = {\n /**\n * Allocate one zeroed polynomial/vector container.\n * @param n - Number of coefficients to allocate.\n * @returns Fresh typed container.\n */\n newPoly: TypedCons<T>;\n /** Polynomial size, typically `256`. */\n N: number;\n /** Prime modulus used for all coefficient arithmetic. */\n Q: number;\n /** Inverse transform normalization factor:\n * `256**-1 mod q` for Dilithium, `128**-1 mod q` for Kyber.\n */\n F: number;\n /** Principal root of unity for the transform domain. */\n ROOT_OF_UNITY: number;\n /** Number of bits used for bit-reversal ordering. */\n brvBits: number;\n /** `true` for Kyber/ML-KEM mode, `false` for Dilithium/ML-DSA mode. */\n isKyber: boolean;\n};\n\n/** Constructor function for typed polynomial containers. */\nexport type TypedCons<T extends TypedArray> = (n: number) => T;\n\ntype Crystals<T extends TypedArray> = {\n mod: (a: number, modulo?: number) => number;\n smod: (a: number, modulo?: number) => number;\n nttZetas: T;\n NTT: {\n /** Forward transform in place. Mutates and returns `r`. */\n encode: (r: T) => T;\n /** Inverse transform in place. Mutates and returns `r`. */\n decode: (r: T) => T;\n };\n bitsCoder: (d: number, c: Coder<number, number>) => BytesCoderLen<T>;\n};\n\n/**\n * Creates shared modular arithmetic, NTT, and packing helpers for CRYSTALS schemes.\n * @param opts - Polynomial and transform parameters. See {@link CrystalOpts}.\n * @returns CRYSTALS arithmetic and encoding helpers.\n * @example\n * Create shared modular arithmetic and NTT helpers for a CRYSTALS parameter set.\n * ```ts\n * const crystals = genCrystals({\n * newPoly: (n) => new Uint16Array(n),\n * N: 256,\n * Q: 3329,\n * F: 3303,\n * ROOT_OF_UNITY: 17,\n * brvBits: 7,\n * isKyber: true,\n * });\n * const reduced = crystals.mod(-1);\n * ```\n */\nexport const genCrystals = <T extends TypedArray>(opts: CrystalOpts<T>): TRet<Crystals<T>> => {\n // isKyber: true means Kyber, false means Dilithium\n const { newPoly, N, Q, F, ROOT_OF_UNITY, brvBits, isKyber } = opts;\n // Normalize JS `%` into the canonical Z_m representative `[0, modulo-1]` expected by\n // FIPS 203 §2.3 / FIPS 204 §2.3 before downstream mod-q arithmetic.\n const mod = (a: number, modulo = Q): number => {\n const result = a % modulo | 0;\n return (result >= 0 ? result | 0 : (modulo + result) | 0) | 0;\n };\n // FIPS 204 §7.4 uses the centered `mod ±` representative for low bits, keeping the\n // positive midpoint when `modulo` is even.\n // Center to `[-floor((modulo-1)/2), floor(modulo/2)]`.\n const smod = (a: number, modulo = Q): number => {\n const r = mod(a, modulo) | 0;\n return (r > modulo >> 1 ? (r - modulo) | 0 : r) | 0;\n };\n // Kyber uses the FIPS 203 Appendix A `BitRev_7` table here via the first 128 entries, while\n // Dilithium uses the FIPS 204 §7.5 / Appendix B `BitRev_8` zetas table over all 256 entries.\n function getZettas() {\n const out = newPoly(N);\n for (let i = 0; i < N; i++) {\n const b = reverseBits(i, brvBits);\n const p = BigInt(ROOT_OF_UNITY) ** BigInt(b) % BigInt(Q);\n out[i] = Number(p) | 0;\n }\n return out;\n }\n const nttZetas = getZettas();\n\n // Number-Theoretic Transform\n // Explained: https://electricdusk.com/ntt.html\n\n // Kyber has slightly different params, since there is no 512th primitive root of unity mod q,\n // only 256th primitive root of unity mod. Which also complicates MultiplyNTT.\n\n const field = {\n add: (a: number, b: number) => mod((a | 0) + (b | 0)) | 0,\n sub: (a: number, b: number) => mod((a | 0) - (b | 0)) | 0,\n mul: (a: number, b: number) => mod((a | 0) * (b | 0)) | 0,\n inv: (_a: number) => {\n throw new Error('not implemented');\n },\n };\n const nttOpts = {\n N,\n roots: nttZetas as any,\n invertButterflies: true,\n skipStages: isKyber ? 1 : 0,\n brp: false,\n };\n const dif = FFTCore(field, { dit: false, ...nttOpts });\n const dit = FFTCore(field, { dit: true, ...nttOpts });\n const NTT = {\n encode: (r: T): T => {\n return dif(r) as any;\n },\n decode: (r: T): T => {\n dit(r as any);\n // The inverse-NTT normalization factor is family-specific: FIPS 203 Algorithm 10 line 14\n // uses `128^-1 mod q` for Kyber, while FIPS 204 Algorithm 42 lines 21-23 use `256^-1 mod q`.\n // kyber uses 128 here, because brv && stuff\n for (let i = 0; i < r.length; i++) r[i] = mod(F * r[i]);\n return r;\n },\n };\n // Pack one little-endian `d`-bit word per coefficient, matching FIPS 203 ByteEncode /\n // ByteDecode and the FIPS 204 BitsToBytes-based polynomial packing helpers.\n const bitsCoder = (d: number, c: Coder<number, number>): TRet<BytesCoderLen<T>> => {\n const mask = getMask(d);\n const bytesLen = d * (N / 8);\n return {\n bytesLen,\n encode: (poly_: TArg<T>): TRet<Uint8Array> => {\n const poly = poly_ as T;\n const r = new Uint8Array(bytesLen);\n for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < poly.length; i++) {\n buf |= (c.encode(poly[i]) & mask) << bufLen;\n bufLen += d;\n for (; bufLen >= 8; bufLen -= 8, buf >>= 8) r[pos++] = buf & getMask(bufLen);\n }\n return r as TRet<Uint8Array>;\n },\n decode: (bytes: TArg<Uint8Array>): TRet<T> => {\n const r = newPoly(N);\n for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < bytes.length; i++) {\n buf |= bytes[i] << bufLen;\n bufLen += 8;\n for (; bufLen >= d; bufLen -= d, buf >>= d) r[pos++] = c.decode(buf & mask);\n }\n return r as TRet<T>;\n },\n } as TRet<BytesCoderLen<T>>;\n };\n\n return {\n mod,\n smod,\n nttZetas: nttZetas as TRet<T>,\n NTT: {\n encode: (r: TArg<T>): TRet<T> => NTT.encode(r as T) as TRet<T>,\n decode: (r: TArg<T>): TRet<T> => NTT.decode(r as T) as TRet<T>,\n },\n bitsCoder: bitsCoder as TRet<Crystals<T>>['bitsCoder'],\n };\n};\n\nconst createXofShake =\n (shake: typeof shake128): TRet<XOF> =>\n (seed: TArg<Uint8Array>, blockLen?: number) => {\n if (!blockLen) blockLen = shake.blockLen;\n // Optimizations that won't mater:\n // - cached seed update (two .update(), on start and on the end)\n // - another cache which cloned into working copy\n\n // Faster than multiple updates, since seed less than blockLen\n const _seed = new Uint8Array(seed.length + 2);\n _seed.set(seed);\n const seedLen = seed.length;\n const buf = new Uint8Array(blockLen); // == shake128.blockLen\n let h = shake.create({});\n let calls = 0;\n let xofs = 0;\n return {\n stats: () => ({ calls, xofs }),\n get: (x: number, y: number) => {\n // Rebind to `seed || x || y` so callers can implement the spec's per-coordinate\n // SHAKE inputs like `rho || j || i` and `rho || IntegerToBytes(counter, 2)`.\n _seed[seedLen + 0] = x;\n _seed[seedLen + 1] = y;\n h.destroy();\n h = shake.create({}).update(_seed);\n calls++;\n return () => {\n xofs++;\n return h.xofInto(buf) as TRet<Uint8Array>;\n };\n },\n clean: () => {\n h.destroy();\n cleanBytes(buf, _seed);\n },\n };\n };\n\n/**\n * SHAKE128-based extendable-output reader factory used by ML-KEM.\n * `get(x, y)` selects one coordinate pair at a time; calling it again invalidates previously\n * returned readers, and each squeeze reuses one mutable internal output buffer.\n * @param seed - Seed bytes for the reader.\n * @param blockLen - Optional output block length.\n * @returns Stateful XOF reader.\n * @example\n * Build the ML-KEM SHAKE128 matrix expander and read one block.\n * ```ts\n * import { randomBytes } from '@noble/post-quantum/utils.js';\n * import { XOF128 } from '@noble/post-quantum/_crystals.js';\n * const reader = XOF128(randomBytes(32));\n * const block = reader.get(0, 0)();\n * ```\n */\nexport const XOF128: TRet<XOF> = /* @__PURE__ */ createXofShake(shake128);\n/**\n * SHAKE256-based extendable-output reader factory used by ML-DSA.\n * `get(x, y)` appends raw one-byte coordinates to the seed, invalidates previously returned\n * readers, and reuses one mutable internal output buffer for each squeeze.\n * @param seed - Seed bytes for the reader.\n * @param blockLen - Optional output block length.\n * @returns Stateful XOF reader.\n * @example\n * Build the ML-DSA SHAKE256 coefficient expander and read one block.\n * ```ts\n * import { randomBytes } from '@noble/post-quantum/utils.js';\n * import { XOF256 } from '@noble/post-quantum/_crystals.js';\n * const reader = XOF256(randomBytes(32));\n * const block = reader.get(0, 0)();\n * ```\n */\nexport const XOF256: TRet<XOF> = /* @__PURE__ */ createXofShake(shake256);\n","/**\n * ML-KEM: Module Lattice-based Key Encapsulation Mechanism from\n * [FIPS-203](https://csrc.nist.gov/pubs/fips/203/ipd). A.k.a. CRYSTALS-Kyber.\n *\n * Key encapsulation is similar to DH / ECDH (think X25519), with important differences:\n * * Unlike in ECDH, we can't verify if it was \"Bob\" who've sent the shared secret\n * * Unlike ECDH, it is probabalistic and relies on quality of randomness (CSPRNG).\n * * Decapsulation never throws an error, even when shared secret was\n * encrypted by a different public key. It will just return a different shared secret.\n *\n * There are some concerns with regards to security: see\n * [djb blog](https://blog.cr.yp.to/20231003-countcorrectly.html) and\n * [mailing list](https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/W2VOzy0wz_E).\n *\n * Has similar internals to ML-DSA, but their keys and params are different.\n *\n * Check out [official site](https://www.pq-crystals.org/kyber/resources.shtml),\n * [repo](https://github.com/pq-crystals/kyber),\n * [spec](https://datatracker.ietf.org/doc/draft-cfrg-schwabe-kyber/).\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { sha3_256, sha3_512, shake256 } from '@noble/hashes/sha3.js';\nimport { type CHash, swap32IfBE, u32 } from '@noble/hashes/utils.js';\nimport { genCrystals, type XOF, XOF128 } from './_crystals.ts';\nimport {\n abytes,\n cleanBytes,\n type Coder,\n copyBytes,\n equalBytes,\n getMask,\n type KEM,\n randomBytes,\n splitCoder,\n type TArg,\n type TRet,\n vecCoder,\n} from './utils.ts';\n\n/** Key encapsulation mechanism interface */\n\nconst N = 256; // Kyber (not FIPS-203) supports different lengths, but all std modes were using 256\nconst Q = 3329; // 13*(2**8)+1, modulo prime\nconst F = 3303; // 3303 ≡ 128**(−1) mod q (FIPS-203)\nconst ROOT_OF_UNITY = 17; // ζ = 17 ∈ Zq is a primitive 256-th root of unity modulo Q. ζ**128 ≡−1\n// treeshake: keep genCrystals behind the object so PARAMS-only bundles can drop it entirely.\n// Shared CRYSTALS helper in the ML-KEM branch: Kyber mode, 7-bit bit-reversal,\n// and Uint16Array polys because current coefficients stay reduced modulo q.\nconst crystals = /* @__PURE__ */ genCrystals({\n N,\n Q,\n F,\n ROOT_OF_UNITY,\n newPoly: (n: number): TRet<Uint16Array> => new Uint16Array(n) as TRet<Uint16Array>,\n brvBits: 7,\n isKyber: true,\n});\n\n/** FIPS 203: 7. Parameter Sets */\n/** Public ML-KEM parameter-set description. */\nexport type KEMParam = {\n /** Polynomial size. */\n N: number;\n /** Module rank. */\n K: number;\n /** Prime modulus. */\n Q: number;\n /** CBD parameter used for secret-key noise. */\n ETA1: number;\n /** CBD parameter used for error noise. */\n ETA2: number;\n /** Compression width for the `u` vector. */\n du: number;\n /** Compression width for the `v` polynomial. */\n dv: number;\n /** Required strength of the randomness source in bits. */\n RBGstrength: number;\n};\n/** Internal params of ML-KEM versions */\n// prettier-ignore\n/** Built-in ML-KEM parameter presets keyed by the public export names\n * `ml_kem512` / `ml_kem768` / `ml_kem1024`.\n * `RBGstrength` is Table 2's required randomness-source strength in bits,\n * not a generic security label.\n */\nexport const PARAMS: Record<string, KEMParam> = /* @__PURE__ */ (() =>\n Object.freeze({\n 512: Object.freeze({ N, Q, K: 2, ETA1: 3, ETA2: 2, du: 10, dv: 4, RBGstrength: 128 }),\n 768: Object.freeze({ N, Q, K: 3, ETA1: 2, ETA2: 2, du: 10, dv: 4, RBGstrength: 192 }),\n 1024: Object.freeze({ N, Q, K: 4, ETA1: 2, ETA2: 2, du: 11, dv: 5, RBGstrength: 256 }),\n } as const))();\n\n// FIPS-203: compress/decompress\nconst compress = (d: number): Coder<number, number> => {\n // d=12 is the ByteEncode12/ByteDecode12 path, not lossy compression.\n // ByteDecode12 interprets each 12-bit word modulo q; without that reduction the public-key\n // modulus check in encapsulate() becomes a no-op for malformed coefficients like 4095.\n if (d >= 12) return { encode: (i: number) => i, decode: (i: number) => (i >= Q ? i - Q : i) };\n // Comments map to python implementation in RFC (draft-cfrg-schwabe-kyber)\n // const round = (i: number) => Math.floor(i + 0.5) | 0;\n const a = 2 ** (d - 1);\n return {\n // This only matches standalone Compress_d after bitsCoder masks the result into Z_(2^d).\n encode: (i: number) => ((i << d) + Q / 2) / Q,\n // const decompress = (i: number) => round((Q / 2 ** d) * i);\n decode: (i: number) => (i * Q + a) >>> d,\n };\n};\n\n// Raw ByteEncode_d / ByteDecode_d from FIPS 203 operate on d-bit words directly.\n// That differs from `polyCoder(d)` for d<12, where noble folds packing together with the lossy\n// ciphertext compression step used by u/v. Tests that exercise the spec's raw packing surface need\n// this exact non-lossy variant instead.\nconst byteCoder = (d: number) =>\n crystals.bitsCoder(\n d,\n d === 12\n ? { encode: (i: number) => i, decode: (i: number) => (i >= Q ? i - Q : i) }\n : { encode: (i: number) => i, decode: (i: number) => i }\n );\n\n// NOTE: we merge encoding and compress because it is faster, also both require same d param\n// d=12 is the ByteEncode12/ByteDecode12 path rather than compression, and caller-side\n// public-key modulus checks route through this helper's decode/encode roundtrip.\n// Converts between bytes and d-bits compressed representation.\n// Kinda like convertRadix2 from @scure/base.\n// decode(encode(t)) == t, but there is loss of information on encode(decode(t))\nconst polyCoder = (d: number) => (d === 12 ? byteCoder(12) : crystals.bitsCoder(d, compress(d)));\n\n// Poly is mod Q, so 12 bits\ntype Poly = Uint16Array;\n\nfunction polyAdd(a_: TArg<Poly>, b_: TArg<Poly>) {\n const a = a_ as Poly;\n const b = b_ as Poly;\n // Mutates `a` in place; callers must pass two N=256 polynomials.\n for (let i = 0; i < N; i++) a[i] = crystals.mod(a[i] + b[i]); // a += b\n}\nfunction polySub(a_: TArg<Poly>, b_: TArg<Poly>) {\n const a = a_ as Poly;\n const b = b_ as Poly;\n // Mutates `a` in place; callers must pass two N=256 polynomials.\n for (let i = 0; i < N; i++) a[i] = crystals.mod(a[i] - b[i]); // a -= b\n}\n\n// FIPS-203: Computes the product of two degree-one polynomials with respect to a quadratic modulus\nfunction BaseCaseMultiply(a0: number, a1: number, b0: number, b1: number, zeta: number) {\n // `zeta` here is Algorithm 11's γ = ζ^(2BitRev_7(i)+1).\n const c0 = crystals.mod(a1 * b1 * zeta + a0 * b0);\n const c1 = crystals.mod(a0 * b1 + a1 * b0);\n return { c0, c1 };\n}\n\n// FIPS-203: Computes the product (in the ring Tq) of two NTT representations.\n// Works in place on `f`; `g` is read-only and both inputs must already be in NTT form.\nfunction MultiplyNTTs(f_: TArg<Poly>, g_: TArg<Poly>): TRet<Poly> {\n const f = f_ as Poly;\n const g = g_ as Poly;\n for (let i = 0; i < N / 2; i++) {\n let z = crystals.nttZetas[64 + (i >> 1)];\n if (i & 1) z = -z;\n const { c0, c1 } = BaseCaseMultiply(f[2 * i + 0], f[2 * i + 1], g[2 * i + 0], g[2 * i + 1], z);\n f[2 * i + 0] = c0;\n f[2 * i + 1] = c1;\n }\n return f as TRet<Poly>;\n}\n\ntype PRF = (l: number, key: Uint8Array, nonce: number) => Uint8Array;\n\ntype XofGet = ReturnType<ReturnType<XOF>['get']>;\n\ntype KyberOpts = KEMParam & {\n HASH256: CHash;\n HASH512: CHash;\n KDF: CHash<any, { dkLen?: number }>;\n XOF: XOF; // (seed: Uint8Array, len: number, x: number, y: number) => Uint8Array;\n PRF: PRF;\n};\n\n// Return poly in NTT representation\nfunction SampleNTT(xof_: TArg<XofGet>): TRet<Poly> {\n const xof = xof_ as XofGet;\n // The reader must already bind the Algorithm 7 seed||j||i bytes\n // and return block lengths divisible by 3.\n const r: Poly = new Uint16Array(N);\n for (let j = 0; j < N; ) {\n const b = xof();\n if (b.length % 3) throw new Error('SampleNTT: unaligned block');\n for (let i = 0; j < N && i + 3 <= b.length; i += 3) {\n const d1 = ((b[i + 0] >> 0) | (b[i + 1] << 8)) & 0xfff;\n const d2 = ((b[i + 1] >> 4) | (b[i + 2] << 4)) & 0xfff;\n if (d1 < Q) r[j++] = d1;\n if (j < N && d2 < Q) r[j++] = d2;\n }\n }\n return r as TRet<Poly>;\n}\n\n// Sampling from the centered binomial distribution\n// Returns poly with small coefficients (noise/errors) stored modulo q in ordinary coefficient form.\n// Current callers only use Table 2 eta values {2,3} and PRF outputs of exactly 64*eta bytes.\nconst sampleCBDBytes = (buf: TArg<Uint8Array>, eta: number): TRet<Poly> => {\n const r: Poly = new Uint16Array(N);\n // CBD consumes the PRF bitstream in little-endian byte order; normalize the word view on BE,\n // then swap it back so callers still observe `buf` as read-only.\n const b32 = u32(buf);\n swap32IfBE(b32);\n let len = 0;\n for (let i = 0, p = 0, bb = 0, t0 = 0; i < b32.length; i++) {\n let b = b32[i];\n for (let j = 0; j < 32; j++) {\n bb += b & 1;\n b >>= 1;\n len += 1;\n if (len === eta) {\n t0 = bb;\n bb = 0;\n } else if (len === 2 * eta) {\n r[p++] = crystals.mod(t0 - bb);\n bb = 0;\n len = 0;\n }\n }\n }\n swap32IfBE(b32);\n if (len) throw new Error(`sampleCBD: leftover bits: ${len}`);\n return r as TRet<Poly>;\n};\n\nfunction sampleCBD(\n PRF_: TArg<PRF>,\n seed: TArg<Uint8Array>,\n nonce: number,\n eta: number\n): TRet<Poly> {\n const PRF = PRF_ as PRF;\n return sampleCBDBytes(PRF((eta * N) / 4, seed, nonce), eta);\n}\n\n// K-PKE\n// Internal ML-KEM subroutine only: exact 32-byte `seed` / `msg` inputs\n// come from Algorithms 13-15, and the helper mutates decoded temporary\n// polynomials in place while leaving caller byte arrays unchanged.\nconst genKPKE = (opts_: TArg<KyberOpts>) => {\n const opts = opts_ as KyberOpts;\n const { K, PRF, XOF, HASH512, ETA1, ETA2, du, dv } = opts;\n const poly1 = polyCoder(1);\n const polyV = polyCoder(dv);\n const polyU = polyCoder(du);\n const publicCoder = splitCoder('publicKey', vecCoder(polyCoder(12), K), 32);\n const secretCoder = vecCoder(polyCoder(12), K);\n const cipherCoder = splitCoder('ciphertext', vecCoder(polyU, K), polyV);\n const seedCoder = splitCoder('seed', 32, 32);\n return {\n secretCoder,\n lengths: {\n secretKey: secretCoder.bytesLen,\n publicKey: publicCoder.bytesLen,\n cipherText: cipherCoder.bytesLen,\n },\n keygen: (seed: TArg<Uint8Array>) => {\n abytes(seed, 32, 'seed');\n const seedDst = new Uint8Array(33);\n seedDst.set(seed);\n // FIPS 203 Algorithm 13 appends the parameter-set byte `k`\n // before `G(d || k)`, so expanding the same 32-byte seed\n // under a different ML-KEM parameter set yields unrelated keys.\n seedDst[32] = K;\n const seedHash = HASH512(seedDst);\n\n const [rho, sigma] = seedCoder.decode(seedHash);\n const sHat: Poly[] = [];\n const tHat: Poly[] = [];\n for (let i = 0; i < K; i++) sHat.push(crystals.NTT.encode(sampleCBD(PRF, sigma, i, ETA1)));\n const x = XOF(rho);\n for (let i = 0; i < K; i++) {\n const e = crystals.NTT.encode(sampleCBD(PRF, sigma, K + i, ETA1));\n for (let j = 0; j < K; j++) {\n const aji = SampleNTT(x.get(j, i)); // A[i][j], inplace\n polyAdd(e, MultiplyNTTs(aji, sHat[j]));\n }\n tHat.push(e); // t ← A ◦ s + e\n }\n x.clean();\n const res = {\n publicKey: publicCoder.encode([tHat, rho]),\n secretKey: secretCoder.encode(sHat),\n };\n cleanBytes(rho, sigma, sHat, tHat, seedDst, seedHash);\n return res;\n },\n encrypt: (\n publicKey: TArg<Uint8Array>,\n msg: TArg<Uint8Array>,\n seed: TArg<Uint8Array>\n ): TRet<Uint8Array> => {\n const [tHat, rho] = publicCoder.decode(publicKey);\n const rHat = [];\n for (let i = 0; i < K; i++) rHat.push(crystals.NTT.encode(sampleCBD(PRF, seed, i, ETA1)));\n const x = XOF(rho);\n const tmp2 = new Uint16Array(N);\n const u = [];\n for (let i = 0; i < K; i++) {\n const e1 = sampleCBD(PRF, seed, K + i, ETA2);\n const tmp = new Uint16Array(N);\n for (let j = 0; j < K; j++) {\n const aij = SampleNTT(x.get(i, j)); // A[j][i], inplace transpose access\n polyAdd(tmp, MultiplyNTTs(aij, rHat[j])); // t += aij * rHat[j]\n }\n polyAdd(e1, crystals.NTT.decode(tmp)); // e1 += tmp\n u.push(e1);\n polyAdd(tmp2, MultiplyNTTs(tHat[i], rHat[i])); // t2 += tHat[i] * rHat[i]\n cleanBytes(tmp);\n }\n x.clean();\n const e2 = sampleCBD(PRF, seed, 2 * K, ETA2);\n polyAdd(e2, crystals.NTT.decode(tmp2)); // e2 += tmp2\n const v = poly1.decode(msg); // encode plaintext m into polynomial v\n polyAdd(v, e2); // v += e2\n cleanBytes(tHat, rHat, tmp2, e2);\n return cipherCoder.encode([u, v]) as TRet<Uint8Array>;\n },\n decrypt: (cipherText: TArg<Uint8Array>, privateKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n const [u, v] = cipherCoder.decode(cipherText);\n const sk = secretCoder.decode(privateKey); // s ← ByteDecode_12(dkPKE)\n const tmp = new Uint16Array(N);\n // tmp += sk[i] * u[i]\n for (let i = 0; i < K; i++) polyAdd(tmp, MultiplyNTTs(sk[i], crystals.NTT.encode(u[i])));\n polySub(v, crystals.NTT.decode(tmp)); // w = v' - tmp\n cleanBytes(tmp, sk, u);\n return poly1.encode(v) as TRet<Uint8Array>;\n },\n };\n};\n\n/**\n * Public ML-KEM wrapper over the internal K-PKE subroutine.\n * `keygen(seed)` and `encapsulate(publicKey, msg)` are deterministic/test-oriented hooks that map\n * more directly to Algorithms 16-17 than to the pure no-input / random-internal Algorithms 19-20.\n * decapsulate() tries to follow the Algorithms 18/21 implicit-reject structure as closely as\n * practical here by re-encrypting, comparing ciphertexts, returning `Khat` on match or `Kbar` on\n * mismatch, and zeroizing the non-returned shared-secret candidate; JS/JIT still provides no\n * constant-time guarantees for that path.\n */\nfunction createKyber(opts: TArg<KyberOpts>): TRet<KEM> {\n const rawOpts = opts as KyberOpts;\n const KPKE = genKPKE(rawOpts);\n const { HASH256, HASH512, KDF } = rawOpts;\n const { secretCoder: KPKESecretCoder, lengths } = KPKE;\n const secretCoder = splitCoder('secretKey', lengths.secretKey, lengths.publicKey, 32, 32);\n const msgLen = 32;\n const seedLen = 64;\n const kemLengths = Object.freeze({\n ...lengths,\n seed: 64,\n msg: msgLen,\n msgRand: msgLen,\n secretKey: secretCoder.bytesLen,\n });\n return Object.freeze({\n info: Object.freeze({ type: 'ml-kem' }),\n lengths: kemLengths,\n keygen: (seed: TArg<Uint8Array> = randomBytes(seedLen)) => {\n abytes(seed, seedLen, 'seed');\n const { publicKey, secretKey: sk } = KPKE.keygen(seed.subarray(0, 32));\n const publicKeyHash = HASH256(publicKey);\n // (dkPKE||ek||H(ek)||z)\n const secretKey = secretCoder.encode([sk, publicKey, publicKeyHash, seed.subarray(32)]);\n cleanBytes(sk, publicKeyHash);\n return {\n publicKey: publicKey as TRet<Uint8Array>,\n secretKey: secretKey as TRet<Uint8Array>,\n };\n },\n getPublicKey: (secretKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n const [_sk, publicKey, _publicKeyHash, _z] = secretCoder.decode(secretKey);\n return Uint8Array.from(publicKey) as TRet<Uint8Array>;\n },\n encapsulate: (publicKey: TArg<Uint8Array>, msg: TArg<Uint8Array> = randomBytes(msgLen)) => {\n abytes(publicKey, lengths.publicKey, 'publicKey');\n abytes(msg, msgLen, 'message');\n\n // FIPS-203 includes additional verification check for modulus\n const eke = publicKey.subarray(0, 384 * opts.K);\n // Copy because of inplace encoding\n const ek = KPKESecretCoder.encode(KPKESecretCoder.decode(copyBytes(eke)));\n // (Modulus check.) Perform the computation ek ← ByteEncode12(ByteDecode12(eke)).\n // If ek = ̸ eke, the input is invalid. (See Section 4.2.1.)\n if (!equalBytes(ek, eke)) {\n cleanBytes(ek);\n throw new Error('ML-KEM.encapsulate: wrong publicKey modulus');\n }\n cleanBytes(ek);\n // derive randomness\n const kr = HASH512.create().update(msg).update(HASH256(publicKey)).digest();\n const cipherText = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));\n cleanBytes(kr.subarray(32));\n return {\n cipherText: cipherText as TRet<Uint8Array>,\n sharedSecret: kr.subarray(0, 32) as TRet<Uint8Array>,\n };\n },\n decapsulate: (cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n abytes(secretKey, secretCoder.bytesLen, 'secretKey'); // 768*k + 96\n abytes(cipherText, lengths.cipherText, 'cipherText'); // 32(du*k + dv)\n // test ← H(dk[384𝑘 ∶ 768𝑘 + 32])) .\n const k768 = secretCoder.bytesLen - 96;\n const start = k768 + 32;\n const test = HASH256(secretKey.subarray(k768 / 2, start));\n // If test ≠ dk[768𝑘 + 32 ∶ 768𝑘 + 64], then input checking has failed.\n if (!equalBytes(test, secretKey.subarray(start, start + 32)))\n throw new Error('invalid secretKey: hash check failed');\n const [sk, publicKey, publicKeyHash, z] = secretCoder.decode(secretKey);\n const msg = KPKE.decrypt(cipherText, sk);\n // derive randomness, Khat, rHat = G(mHat || h)\n const kr = HASH512.create().update(msg).update(publicKeyHash).digest();\n const Khat = kr.subarray(0, 32);\n // re-encrypt using the derived randomness\n const cipherText2 = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));\n // if ciphertexts do not match, “implicitly reject”\n const isValid = equalBytes(cipherText, cipherText2);\n const Kbar = KDF.create({ dkLen: 32 }).update(z).update(cipherText).digest();\n cleanBytes(msg, cipherText2, !isValid ? Khat : Kbar);\n return (isValid ? Khat : Kbar) as TRet<Uint8Array>;\n },\n });\n}\n\n// FIPS 203's PRF_eta binding: current callers use only 32-byte keys, one-byte nonces,\n// and dkLen values {128, 192}; out-of-range nonce numbers still wrap modulo 256 here.\nfunction shakePRF(dkLen: number, key: TArg<Uint8Array>, nonce: number): TRet<Uint8Array> {\n return shake256\n .create({ dkLen })\n .update(key)\n .update(new Uint8Array([nonce]))\n .digest() as TRet<Uint8Array>;\n}\n\n// Fixed ML-KEM hash/XOF bindings. `KDF` here is the spec's fixed 32-byte `J` call,\n// and swapping any field changes the scheme rather than tuning an internal dependency.\nconst opts = /* @__PURE__ */ (() => ({\n HASH256: sha3_256,\n HASH512: sha3_512,\n KDF: shake256,\n XOF: XOF128,\n PRF: shakePRF,\n}))();\n// Parameter-set instantiation step for the spec's \"ML-KEM-x\" names; current correctness relies\n// on the internal PARAMS rows rather than local validation of arbitrary KEMParam objects.\nconst mk = (params: KEMParam) =>\n createKyber({\n ...opts,\n ...params,\n });\n\n/**\n * ML-KEM-512: Table 2 row `k=2, η1=3, η2=2, du=10, dv=4`; Table 3 sizes `800/1632/768/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem512: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[512]))();\n/**\n * ML-KEM-768: Table 2 row `k=3, η1=2, η2=2, du=10, dv=4`; Table 3 sizes `1184/2400/1088/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem768: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[768]))();\n/**\n * ML-KEM-1024: Table 2 row `k=4, η1=2, η2=2, du=11, dv=5`; Table 3 sizes `1568/3168/1568/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem1024: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[1024]))();\n\n// NOTE: for tests only, don't use. This keeps the exact internal ML-KEM math surfaces available\n// without re-implementing them in separate test code.\nexport const __tests: any = /* @__PURE__ */ (() =>\n Object.freeze({\n Compress_d: (x: number, d: number) => {\n if (d < 1 || d > 11) throw new Error(`Compress_d: expected d in [1..11], got ${d}`);\n return compress(d).encode(x) & getMask(d);\n },\n Decompress_d: (y: number, d: number) => {\n if (d < 1 || d > 11) throw new Error(`Decompress_d: expected d in [1..11], got ${d}`);\n return compress(d).decode(y);\n },\n ByteEncode_d: (F: TArg<Uint16Array>, d: number) => {\n if (d < 1 || d > 12) throw new Error(`ByteEncode_d: expected d in [1..12], got ${d}`);\n return byteCoder(d).encode(F as TRet<Uint16Array>);\n },\n ByteDecode_d: (B: TArg<Uint8Array>, d: number) => {\n if (d < 1 || d > 12) throw new Error(`ByteDecode_d: expected d in [1..12], got ${d}`);\n return byteCoder(d).decode(B);\n },\n NTT: (f: TArg<Uint16Array>) => crystals.NTT.encode(Uint16Array.from(f)),\n NTT_inv: (fHat: TArg<Uint16Array>) => crystals.NTT.decode(Uint16Array.from(fHat)),\n MultiplyNTTs: (fHat: TArg<Uint16Array>, gHat: TArg<Uint16Array>) =>\n MultiplyNTTs(Uint16Array.from(fHat), Uint16Array.from(gHat)),\n SamplePolyCBD: (B: TArg<Uint8Array>, eta: number) => {\n abytes(B, 64 * eta, 'B');\n return sampleCBDBytes(B, eta);\n },\n SampleNTT: (B: TArg<Uint8Array>) => {\n abytes(B, 34, 'B');\n const xof = XOF128(B.subarray(0, 32));\n try {\n return SampleNTT(xof.get(B[32], B[33]));\n } finally {\n xof.clean();\n }\n },\n }))();\n","/**\n * Post-Quantum Hybrid Cryptography\n *\n * The current implementation is flawed and likely redundant. We should offer\n * a small, generic API to compose hybrid schemes instead of reimplementing\n * protocol-specific logic (SSH, GPG, etc.) with ad hoc encodings.\n *\n * 1. Core Issues\n * - sign/verify: implemented as two separate operations with different keys.\n * - EC getSharedSecret: could be refactored into a proper KEM.\n * - Multiple calls: keys, signatures, and shared secrets could be\n * concatenated to reduce the number of API invocations.\n * - Reinvention: most libraries add strange domain separations and\n * encodings instead of simple byte concatenation.\n *\n * 2. API Goals\n * - Provide primitives to build hybrids generically.\n * - Avoid embedding SSH- or GPG-specific formats in the core API.\n *\n * 3. Edge Cases\n * • Variable-length signatures:\n * - DER-encoded (Weierstrass curves).\n * - Falcon (unpadded).\n * - Concatenation works only if length is fixed; otherwise a length\n * prefix is required (but that breaks compatibility).\n *\n * • getSharedSecret:\n * - Default: non-KEM (authenticated ECDH).\n * - KEM conversion: generate a random SK to remove implicit auth.\n *\n * 4. Common Pitfalls\n * - Seed expansion:\n * • Expanding a small seed into multiple keys reduces entropy.\n * • API should allow identity mapping (no expansion).\n *\n * - Skipping full point encoding:\n * • Some omit the compression byte (parity) for WebCrypto compatibility.\n * • Better: hash the raw secret; coordinate output is already non-uniform.\n * • Some curves (e.g., X448) produce secrets that must be re-hashed to match\n * symmetric-key lengths.\n *\n * - Combiner inconsistencies:\n * • Different domain separations and encodings across libraries.\n * • Should live at the application layer, since key lengths vary.\n *\n * 5. Protocol Examples\n * - SSH:\n * • Concatenate keys.\n * • Combiner: SHA-512.\n *\n * - GPG:\n * • Concatenate keys.\n * • Combiner:\n * SHA3-256(kemShare || ecdhShare || ciphertext || pubKey || algId || domSep || len(domSep))\n *\n * - TLS:\n * • Transcript-based derivation (HKDF).\n *\n * 6. Relevant Specs & Implementations\n * - IETF Hybrid KEM drafts:\n * • draft-irtf-cfrg-hybrid-kems\n * • draft-connolly-cfrg-xwing-kem\n * • draft-westerbaan-tls-xyber768d00\n *\n * - PQC Libraries:\n * • superdilithium (cyph/pqcrypto.js) – low adoption.\n * • hybrid-pqc (DogeProtocol, quantumcoinproject) – complex encodings.\n *\n * 7. Signatures\n * - Ed25519: fixed-size, easy to support.\n * - Variable-size: introduces custom format requirements; best left to\n * higher-level code.\n *\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { type EdDSA } from '@noble/curves/abstract/edwards.js';\nimport { type MontgomeryECDH } from '@noble/curves/abstract/montgomery.js';\nimport { type ECDSA } from '@noble/curves/abstract/weierstrass.js';\nimport { x25519 } from '@noble/curves/ed25519.js';\nimport { p256, p384 } from '@noble/curves/nist.js';\nimport {\n asciiToBytes,\n bytesToNumberBE,\n bytesToNumberLE,\n concatBytes,\n numberToBytesBE,\n} from '@noble/curves/utils.js';\nimport { expand, extract } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { sha3_256, shake256 } from '@noble/hashes/sha3.js';\nimport { abytes, ahash, anumber, type CHash, type CHashXOF } from '@noble/hashes/utils.js';\nimport { ml_kem1024, ml_kem768 } from './ml-kem.ts';\nimport {\n cleanBytes,\n copyBytes,\n randomBytes,\n splitCoder,\n validateSigOpts,\n validateVerOpts,\n type CryptoKeys,\n type KEM,\n type Signer,\n type TArg,\n type TRet,\n} from './utils.ts';\n\ntype CurveAll = ECDSA | EdDSA | MontgomeryECDH;\ntype CurveECDH = ECDSA | MontgomeryECDH;\ntype CurveSign = ECDSA | EdDSA;\n\n// Can re-use if decide to signatures support, on other hand getSecretKey is specific and ugly\nfunction ecKeygen(curve: CurveAll, allowZeroKey: boolean = false) {\n const lengths = curve.lengths;\n let keygen = curve.keygen;\n if (allowZeroKey) {\n // Only the ECDSA/Weierstrass branch uses raw scalar-byte secret keys here. Edwards seeds are\n // hashed/pruned and Montgomery keys are clamped byte strings, so forcing Point.Fn semantics on\n // those curves would change key construction instead of just relaxing scalar range handling.\n if (!('getSharedSecret' in curve && 'sign' in curve && 'verify' in curve))\n throw new Error('allowZeroKey requires a Weierstrass curve');\n // This legacy flag is really \"skip the +1 shift\" for vector matching, not \"accept scalar 0\".\n // It swaps seeded Weierstrass keygen from reduction into [1, ORDER) to direct reduction into\n // [0, ORDER), which preserves exact reduced bytes but still leaves scalar 0 invalid.\n // This is ugly, but we need to return exact results here.\n const wCurve = curve as ECDSA;\n const Fn = wCurve.Point.Fn;\n // Unlike noble-curves' seeded Weierstrass keygen, this path removes the post-reduction +1.\n // That is enough to match exact reduced-vector bytes, but an all-zero seed still reduces to\n // scalar 0 here and getPublicKey(secretKey) throws instead of \"allowing zero\".\n keygen = (seed: TArg<Uint8Array> = randomBytes(lengths.seed)) => {\n abytes(seed, lengths.seed!, 'seed');\n const seedScalar = Fn.isLE ? bytesToNumberLE(seed) : bytesToNumberBE(seed);\n // Reduce directly into [0, ORDER); scalar 0 still stays invalid.\n const secretKey = Fn.toBytes(Fn.create(seedScalar));\n return {\n secretKey: secretKey as TRet<Uint8Array>,\n publicKey: curve.getPublicKey(secretKey) as TRet<Uint8Array>,\n };\n };\n }\n return {\n lengths: { secretKey: lengths.secretKey, publicKey: lengths.publicKey, seed: lengths.seed },\n keygen: (seed?: TArg<Uint8Array>) =>\n keygen(seed) as TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }>,\n getPublicKey: (secretKey: TArg<Uint8Array>) =>\n curve.getPublicKey(secretKey) as TRet<Uint8Array>,\n };\n}\n\n/**\n * Wraps an ECDH-capable curve as a KEM.\n * Shared secrets stay in the wrapped curve's raw ECDH byte format with no built-in KDF.\n * On SEC 1 / Weierstrass curves, that means the compressed shared-point body without the\n * 1-byte `0x02` / `0x03` prefix.\n * The X25519 path also leaves RFC 7748's optional all-zero shared-secret check to callers.\n * @param curve - Curve with `getSharedSecret`.\n * @param allowZeroKey - Legacy vector-matching toggle for Weierstrass keygen.\n * On Weierstrass curves this removes the usual post-reduction `+1` shift, changing seeded scalar\n * reduction from `[1, ORDER)` to direct reduction into `[0, ORDER)`. It does not make scalar zero\n * valid: an all-zero seed still derives scalar `0` and throws in `curve.getPublicKey(...)`.\n * Only supported on Weierstrass/ECDSA curves.\n * @returns KEM wrapper over the curve.\n * @throws If the curve does not expose `getSharedSecret`. {@link Error}\n * @example\n * Wrap an ECDH-capable curve as a generic KEM.\n * ```ts\n * import { x25519 } from '@noble/curves/ed25519.js';\n * import { ecdhKem } from '@noble/post-quantum/hybrid.js';\n * const kem = ecdhKem(x25519);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function ecdhKem(curve: CurveECDH, allowZeroKey: boolean = false): TRet<KEM> {\n const kg = ecKeygen(curve, allowZeroKey);\n if (!curve.getSharedSecret) throw new Error('wrong curve'); // ed25519 doesn't have one!\n return {\n lengths: { ...kg.lengths, msg: kg.lengths.seed, cipherText: kg.lengths.publicKey },\n keygen: kg.keygen,\n getPublicKey: kg.getPublicKey,\n encapsulate(\n publicKey: TArg<Uint8Array>,\n rand: TArg<Uint8Array> = randomBytes(curve.lengths.seed)\n ) {\n // Some curve.keygen(seed) paths reuse the provided seed buffer as secretKey; detach caller\n // randomness first so cleanBytes() only wipes wrapper-owned material.\n const seed = copyBytes(rand);\n let ek: Uint8Array | undefined = undefined;\n try {\n ek = this.keygen(seed).secretKey;\n const sharedSecret = this.decapsulate(publicKey, ek);\n const cipherText = curve.getPublicKey(ek) as TRet<Uint8Array>;\n return { sharedSecret, cipherText };\n } finally {\n // Invalid peer public keys can make decapsulation throw; wipe both the detached seed and\n // derived ephemeral secret key even when encapsulation aborts before returning.\n cleanBytes(seed);\n if (ek) cleanBytes(ek);\n }\n },\n decapsulate(cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) {\n const res = curve.getSharedSecret(secretKey, cipherText);\n return (curve.lengths.publicKeyHasPrefix ? res.subarray(1) : res) as TRet<Uint8Array>;\n },\n };\n}\n\n/**\n * Wraps a curve signer as a generic `Signer`.\n * Signatures stay in the wrapped curve's native byte encoding.\n * This wrapper does not normalize or document which per-curve signing options are meaningful.\n * @param curve - Curve with `sign` and `verify`.\n * @param allowZeroKey - Legacy vector-matching toggle for Weierstrass keygen.\n * On Weierstrass curves this removes the usual post-reduction `+1` shift, changing seeded scalar\n * reduction from `[1, ORDER)` to direct reduction into `[0, ORDER)`. It does not make scalar zero\n * valid: an all-zero seed still derives scalar `0` and throws in `curve.getPublicKey(...)`.\n * Only supported on Weierstrass/ECDSA curves.\n * @returns Signer wrapper over the curve.\n * @throws If the curve does not expose `sign` and `verify`. {@link Error}\n * @example\n * Wrap a curve signer as a generic signer.\n * ```ts\n * import { ed25519 } from '@noble/curves/ed25519.js';\n * import { ecSigner } from '@noble/post-quantum/hybrid.js';\n * const signer = ecSigner(ed25519);\n * const sigLen = signer.lengths.signature;\n * ```\n */\nexport function ecSigner(curve: CurveSign, allowZeroKey: boolean = false): TRet<Signer> {\n const kg = ecKeygen(curve, allowZeroKey);\n if (!curve.sign || !curve.verify) throw new Error('wrong curve'); // ed25519 doesn't have one!\n return {\n lengths: { ...kg.lengths, signature: curve.lengths.signature, signRand: 0 },\n keygen: kg.keygen,\n getPublicKey: kg.getPublicKey,\n sign: (message, secretKey, opts = {}) => {\n validateSigOpts(opts);\n // This generic wrapper intentionally keeps the Signer contract to message + key only.\n // Backend-specific knobs like ECDSA extraEntropy or Ed25519ctx context cannot be forwarded\n // uniformly through combineSigners(), so callers that need them must use the curve directly.\n if (opts.extraEntropy !== undefined)\n throw new Error(\n 'ecSigner does not support extraEntropy; use the underlying curve directly'\n );\n if (opts.context !== undefined)\n throw new Error('ecSigner does not support context; use the underlying curve directly');\n return curve.sign(message, secretKey) as TRet<Uint8Array>;\n },\n /** Verify one wrapped curve signature.\n * Returns the wrapped curve's `verify()` result for well-formed inputs. Throws on unsupported\n * generic opts and lets wrapped-curve malformed-input errors escape unchanged.\n */\n verify: (signature, message, publicKey, opts = {}) => {\n validateVerOpts(opts);\n if (opts.context !== undefined)\n throw new Error('ecSigner does not support context; use the underlying curve directly');\n return curve.verify(signature, message, publicKey);\n },\n };\n}\n\nfunction splitLengths<K extends string, T extends { lengths: Partial<Record<K, number>> }>(\n lst: T[],\n name: K\n) {\n // Preserve caller order exactly; raw numeric fields still decode as splitCoder() subarray views.\n return splitCoder(\n name,\n ...lst.map((i) => {\n if (typeof i.lengths[name] !== 'number') throw new Error('wrong length: ' + name);\n return i.lengths[name];\n })\n );\n}\n\n/** Seed-expansion callback used by the hybrid combiners. */\nexport type ExpandSeed = (seed: TArg<Uint8Array>, len: number) => TRet<Uint8Array>;\ntype XOF = CHashXOF<any, { dkLen: number }>;\n\n// It is XOF for most cases, but can be more complex!\n/**\n * Adapts an XOF into an `ExpandSeed` callback.\n * The returned callback interprets its second argument as an output byte length passed as `dkLen`.\n * @param xof - Extendable-output hash function.\n * @returns Seed expander using `dkLen`.\n * @example\n * Adapt an XOF into a seed expander.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * const expandSeed = expandSeedXof(shake256);\n * const seed = expandSeed(new Uint8Array([1]), 4);\n * ```\n */\nexport function expandSeedXof(xof: TArg<XOF>): TRet<ExpandSeed> {\n // Forward the caller seed directly: XOFs are expected to treat inputs as read-only, and this\n // adapter only translates the requested byte length into the hash API's `dkLen` option.\n return ((seed: TArg<Uint8Array>, seedLen: number): TRet<Uint8Array> =>\n (xof as XOF)(seed, { dkLen: seedLen }) as TRet<Uint8Array>) as TRet<ExpandSeed>;\n}\n\n/** Combines public keys, ciphertexts, and shared secrets into one shared secret. */\nexport type Combiner = (\n publicKeys: TArg<Uint8Array[]>,\n cipherTexts: TArg<Uint8Array[]>,\n sharedSecrets: TArg<Uint8Array[]>\n) => TRet<Uint8Array>;\n\nfunction combineKeys(\n realSeedLen: number | undefined, // how much bytes expandSeed expects\n expandSeed_: TArg<ExpandSeed>,\n ...ck_: TArg<CryptoKeys[]>\n) {\n const expandSeed = expandSeed_ as ExpandSeed;\n const ck = ck_ as CryptoKeys[];\n const seedCoder = splitLengths(ck, 'seed');\n const pkCoder = splitLengths(ck, 'publicKey');\n // Allows to use identity functions for combiner/expandSeed\n if (realSeedLen === undefined) realSeedLen = seedCoder.bytesLen;\n anumber(realSeedLen);\n function expandDecapsulationKey(seed: TArg<Uint8Array>): TRet<{\n secretKey: Uint8Array[];\n publicKey: Uint8Array[];\n }> {\n abytes(seed, realSeedLen!);\n const expandedRaw = expandSeed(seed, seedCoder.bytesLen);\n // Identity/subarray expanders can hand back caller-owned seed storage. Detach those outputs so\n // later cleanup can wipe the expanded schedule without mutating the caller's root seed bytes.\n const expandedSeed = expandedRaw.buffer === seed.buffer ? copyBytes(expandedRaw) : expandedRaw;\n const expanded: Uint8Array[] = [];\n const keySecret: Uint8Array[] = [];\n const secretKey: Uint8Array[] = [];\n const publicKey: Uint8Array[] = [];\n let ok = false;\n try {\n // seedCoder.decode() returns zero-copy slices into expandedSeed and can throw before child\n // keygen() runs, so keep the raw expanded buffer separate and copy each child seed before any\n // later cleanup wipes the shared backing bytes.\n for (const part of seedCoder.decode(expandedSeed)) expanded.push(copyBytes(part));\n for (let i = 0; i < ck.length; i++) {\n const keys = ck[i].keygen(expanded[i]);\n keySecret.push(keys.secretKey);\n secretKey.push(copyBytes(keys.secretKey));\n publicKey.push(keys.publicKey);\n }\n ok = true;\n return { secretKey, publicKey } as TRet<{\n secretKey: Uint8Array[];\n publicKey: Uint8Array[];\n }>;\n } finally {\n // Child keygen() can throw after deriving only a prefix of the composite key schedule. Keep\n // the exported copies on success, but wipe all temporary and partially built secret material\n // on either path so failures do not strand derived child seeds in memory.\n cleanBytes(expandedSeed, expanded, keySecret);\n if (!ok) cleanBytes(secretKey);\n }\n }\n return {\n info: { lengths: { seed: realSeedLen, publicKey: pkCoder.bytesLen, secretKey: realSeedLen } },\n getPublicKey(secretKey: TArg<Uint8Array>) {\n // Composite secret keys are root seeds, so public-key derivation reruns key expansion from\n // that seed instead of decoding a packed child-secret-key structure.\n return this.keygen(secretKey).publicKey as TRet<Uint8Array>;\n },\n keygen(seed: TArg<Uint8Array> = randomBytes(realSeedLen)) {\n const { publicKey: pk, secretKey } = expandDecapsulationKey(seed);\n try {\n const publicKey = pkCoder.encode(pk) as TRet<Uint8Array>;\n return { secretKey: seed as TRet<Uint8Array>, publicKey };\n } finally {\n cleanBytes(pk);\n // The exported secretKey is the caller/root seed itself; child secret keys are internal\n // expansion outputs that are cleaned whether encoding succeeds or throws.\n cleanBytes(secretKey);\n }\n },\n expandDecapsulationKey,\n realSeedLen,\n };\n}\n\n// This generic function that combines multiple KEMs into single one\n/**\n * Combines multiple KEMs into one composite KEM.\n * @param realSeedLen - Input seed length expected by `expandSeed`.\n * @param realMsgLen - Shared-secret length returned by `combiner`.\n * @param expandSeed - Seed expander used to derive per-KEM seeds.\n * @param combiner - Combines the per-KEM outputs into one shared secret.\n * @param kems - KEM implementations to combine.\n * @returns Composite KEM.\n * @example\n * Combine multiple KEMs into one composite KEM.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { combineKEMS, expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * const hybrid = combineKEMS(\n * 32,\n * 32,\n * expandSeedXof(shake256),\n * (_pk, _ct, sharedSecrets) => sharedSecrets[0],\n * ml_kem768,\n * ml_kem768\n * );\n * const { publicKey } = hybrid.keygen();\n * ```\n */\nexport function combineKEMS(\n realSeedLen: number | undefined, // how much bytes expandSeed expects\n realMsgLen: number | undefined, // how much bytes combiner returns\n expandSeed: TArg<ExpandSeed>,\n combiner: TArg<Combiner>,\n ...kems: TArg<KEM[]>\n): TRet<KEM> {\n const rawCombiner = combiner as Combiner;\n const rawKems = kems as KEM[];\n const keys = combineKeys(realSeedLen, expandSeed, ...rawKems);\n const ctCoder = splitLengths(rawKems, 'cipherText');\n const pkCoder = splitLengths(rawKems, 'publicKey');\n const msgCoder = splitLengths(rawKems, 'msg');\n if (realMsgLen === undefined) realMsgLen = msgCoder.bytesLen;\n anumber(realMsgLen);\n const lengths = Object.freeze({\n ...keys.info.lengths,\n msg: realMsgLen,\n msgRand: msgCoder.bytesLen,\n cipherText: ctCoder.bytesLen,\n });\n return Object.freeze({\n lengths,\n getPublicKey: keys.getPublicKey,\n keygen: keys.keygen,\n encapsulate(\n pk: TArg<Uint8Array>,\n randomness: TArg<Uint8Array> = randomBytes(msgCoder.bytesLen)\n ) {\n const pks = pkCoder.decode(pk);\n const rand = msgCoder.decode(randomness);\n const sharedSecret: Uint8Array[] = [];\n const cipherText: Uint8Array[] = [];\n try {\n for (let i = 0; i < rawKems.length; i++) {\n const enc = rawKems[i].encapsulate(pks[i], rand[i]);\n sharedSecret.push(enc.sharedSecret);\n cipherText.push(enc.cipherText);\n }\n return {\n // Detach the combiner result before cleanup: a caller-provided combiner may alias one of\n // the child sharedSecret buffers, and those child buffers are zeroized immediately below.\n sharedSecret: copyBytes(rawCombiner(pks, cipherText, sharedSecret)),\n cipherText: ctCoder.encode(cipherText) as TRet<Uint8Array>,\n };\n } finally {\n // Child encapsulation or combiner failures can happen after some components already\n // returned secret material; zeroize whatever was produced before propagating the error.\n cleanBytes(sharedSecret, cipherText);\n }\n },\n decapsulate(ct: TArg<Uint8Array>, seed: TArg<Uint8Array>) {\n const cts = ctCoder.decode(ct);\n const { publicKey, secretKey } = keys.expandDecapsulationKey(seed);\n const sharedSecret = rawKems.map((i, j) => i.decapsulate(cts[j], secretKey[j]));\n try {\n // Detach the decapsulation result before cleanup: the combiner may hand back one of the\n // child shared-secret buffers, and those temporary buffers are zeroized below.\n return copyBytes(rawCombiner(publicKey, cts, sharedSecret));\n } finally {\n // Decapsulation only needs the expanded child secret keys and child shared secrets for this\n // call; keep the caller/root seed intact, but wipe all derived material even on errors.\n cleanBytes(secretKey, sharedSecret);\n }\n },\n });\n}\n// There is no specs for this, but can be useful\n// realSeedLen: how much bytes expandSeed expects.\n/**\n * Combines multiple signers into one composite signer.\n * @param realSeedLen - Input seed length expected by `expandSeed`.\n * @param expandSeed - Seed expander used to derive per-signer seeds.\n * @param signers - Signers to combine.\n * @returns Composite signer.\n * @example\n * Combine multiple signers into one composite signer.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { combineSigners, expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * import { ml_dsa44 } from '@noble/post-quantum/ml-dsa.js';\n * const hybrid = combineSigners(32, expandSeedXof(shake256), ml_dsa44, ml_dsa44);\n * const { publicKey } = hybrid.keygen();\n * ```\n */\nexport function combineSigners(\n realSeedLen: number | undefined,\n expandSeed: TArg<ExpandSeed>,\n ...signers: TArg<Signer[]>\n): TRet<Signer> {\n const rawSigners = signers as Signer[];\n const keys = combineKeys(realSeedLen, expandSeed, ...rawSigners);\n const sigCoder = splitLengths(rawSigners, 'signature');\n const pkCoder = splitLengths(rawSigners, 'publicKey');\n return {\n lengths: { ...keys.info.lengths, signature: sigCoder.bytesLen, signRand: 0 },\n getPublicKey: keys.getPublicKey,\n keygen: keys.keygen,\n sign(message, seed, opts = {}) {\n validateSigOpts(opts);\n // This generic wrapper intentionally keeps the composite signer contract to message + root\n // seed only. Per-signer opts like context or extraEntropy cannot be preserved uniformly\n // across mixed backends, so callers that need them must use the underlying signer directly.\n if (opts.extraEntropy !== undefined)\n throw new Error(\n 'combineSigners does not support extraEntropy; use the underlying signer directly'\n );\n if (opts.context !== undefined)\n throw new Error(\n 'combineSigners does not support context; use the underlying signer directly'\n );\n const { secretKey } = keys.expandDecapsulationKey(seed);\n try {\n const sigs = rawSigners.map((i, j) => i.sign(message, secretKey[j]));\n return sigCoder.encode(sigs) as TRet<Uint8Array>;\n } finally {\n // Composite secret keys are root seeds; the per-signer child secret keys are temporary\n // expansion outputs and must not stay live after the combined signature is produced.\n cleanBytes(secretKey);\n }\n },\n /** Verify one combined signature.\n * Returns `false` when the aggregate signature/publicKey decode succeeds but any child verify\n * check fails. Throws on unsupported generic opts or malformed aggregate encodings.\n */\n verify: (signature, message, publicKey, opts = {}) => {\n validateVerOpts(opts);\n if (opts.context !== undefined)\n throw new Error(\n 'combineSigners does not support context; use the underlying signer directly'\n );\n const pks = pkCoder.decode(publicKey);\n const sigs = sigCoder.decode(signature);\n for (let i = 0; i < rawSigners.length; i++) {\n if (!rawSigners[i].verify(sigs[i], message, pks[i])) return false;\n }\n return true;\n },\n };\n}\n\n/**\n * Builds a QSF hybrid KEM preset from a PQ KEM and an elliptic-curve KEM.\n * The combined shared-secret length follows `kdf.outputLen`; the built-in presets use 32-byte\n * SHA3-256 output, while custom `kdf` choices inherit their own digest size.\n * Its combiner hashes `ss0 || ss1 || ct1 || pk1 || label`, not the full\n * `(c1, c2, ek1, ek2)` example input shape from SP 800-227 equation (15).\n * Labels are encoded with `asciiToBytes()`, so non-ASCII labels are rejected.\n * @param label - Domain-separation label.\n * @param pqc - Post-quantum KEM.\n * @param curveKEM - Classical curve KEM.\n * @param xof - XOF used for seed expansion.\n * @param kdf - Hash used for the final combiner.\n * @returns Hybrid KEM.\n * @example\n * Build a QSF hybrid KEM preset from a PQ KEM and an elliptic-curve KEM.\n * ```ts\n * import { p256 } from '@noble/curves/nist.js';\n * import { sha3_256, shake256 } from '@noble/hashes/sha3.js';\n * import { QSF, ecdhKem } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * const kem = QSF('example', ml_kem768, ecdhKem(p256, true), shake256, sha3_256);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function QSF(\n label: string,\n pqc: TArg<KEM>,\n curveKEM: TArg<KEM>,\n xof: TArg<XOF>,\n kdf: CHash\n): TRet<KEM> {\n ahash(xof);\n ahash(kdf);\n return combineKEMS(\n 32,\n kdf.outputLen,\n expandSeedXof(xof),\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n kdf(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes(label))),\n pqc,\n curveKEM\n );\n}\n\n/** QSF preset combining ML-KEM-768 with P-256. */\nexport const QSF_ml_kem768_p256: TRet<KEM> = /* @__PURE__ */ (() =>\n QSF(\n 'QSF-KEM(ML-KEM-768,P-256)-XOF(SHAKE256)-KDF(SHA3-256)',\n ml_kem768,\n ecdhKem(p256, true),\n shake256,\n sha3_256\n ))();\n/** QSF preset combining ML-KEM-1024 with P-384. */\nexport const QSF_ml_kem1024_p384: TRet<KEM> = /* @__PURE__ */ (() =>\n QSF(\n 'QSF-KEM(ML-KEM-1024,P-384)-XOF(SHAKE256)-KDF(SHA3-256)',\n ml_kem1024,\n ecdhKem(p384, true),\n shake256,\n sha3_256\n ))();\n\n/**\n * Builds the \"KitchenSink\" hybrid KEM combiner.\n * The current builder always derives a fixed 32-byte output,\n * regardless of the hash's native output size.\n * Its HKDF extract step uses implicit zero salt with IKM\n * `hybrid_prk || ss0 || ss1 || ct0 || pk0 || ct1 || pk1 || label`.\n * Its HKDF expand step fixes `info` to `len || 'shared_secret' || ''`.\n * Labels are encoded with `asciiToBytes()`, so non-ASCII labels are rejected.\n * @param label - Domain-separation label.\n * @param pqc - Post-quantum KEM.\n * @param curveKEM - Classical curve KEM.\n * @param xof - XOF used for seed expansion.\n * @param hash - Hash used for HKDF extraction and expansion.\n * @returns Hybrid KEM.\n * @example\n * Build the \"KitchenSink\" hybrid KEM combiner.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { createKitchenSink, ecdhKem } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * import { x25519 } from '@noble/curves/ed25519.js';\n * const kem = createKitchenSink('example', ml_kem768, ecdhKem(x25519), shake256, sha256);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function createKitchenSink(\n label: string,\n pqc: TArg<KEM>,\n curveKEM: TArg<KEM>,\n xof: TArg<XOF>,\n hash: CHash\n): TRet<KEM> {\n ahash(xof);\n ahash(hash);\n return combineKEMS(\n 32,\n 32,\n expandSeedXof(xof),\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) => {\n const preimage = concatBytes(ss[0], ss[1], ct[0], pk[0], ct[1], pk[1], asciiToBytes(label));\n const len = 32;\n const ikm = concatBytes(asciiToBytes('hybrid_prk'), preimage);\n const prk = extract(hash, ikm);\n const info = concatBytes(\n numberToBytesBE(len, 2),\n asciiToBytes('shared_secret'),\n asciiToBytes('')\n );\n const res = expand(hash, prk, info, len);\n cleanBytes(prk, info, ikm, preimage);\n return res;\n },\n pqc,\n curveKEM\n );\n}\n\n// Internal alias only: this stays exactly `ecdhKem(x25519)`\n// and inherits that wrapper's mutation/oracle behavior.\nconst x25519kem = /* @__PURE__ */ ecdhKem(x25519);\n/** KitchenSink preset combining ML-KEM-768 with X25519.\n * Caller randomness splits into 32 ML-KEM coins plus a 32-byte X25519 ephemeral-secret seed.\n */\nexport const KitchenSink_ml_kem768_x25519: TRet<KEM> = /* @__PURE__ */ (() =>\n createKitchenSink(\n 'KitchenSink-KEM(ML-KEM-768,X25519)-XOF(SHAKE256)-KDF(HKDF-SHA-256)',\n ml_kem768,\n x25519kem,\n shake256,\n sha256\n ))();\n\n// Always X25519 and ML-KEM - 768, no point to export\n/** X25519 + ML-KEM-768 hybrid preset.\n * Uses the hard-coded domain-separation label `\\\\.//^\\\\` and hashes only `ct1 || pk1`\n * from the X25519 side in addition to the two component shared secrets.\n */\nexport const ml_kem768_x25519: TRet<KEM> = /* @__PURE__ */ (() =>\n combineKEMS(\n 32,\n 32,\n expandSeedXof(shake256),\n // Awesome label, so much escaping hell in a single line.\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes('\\\\.//^\\\\'))),\n ml_kem768,\n x25519kem\n ))();\n\n/**\n * Internal SEC 1-style KEM wrapper for NIST curves.\n * `nseed` is only the rejection-sampling byte budget for deriving one nonzero scalar:\n * current presets use `128` bytes for P-256 and `48` bytes for P-384.\n * `decapsulate()` returns the uncompressed shared point body `x || y` without the `0x04`\n * prefix, not the SEC 1 `x_P`-only primitive output, because current hybrid combiners hash\n * both coordinates.\n */\nfunction nistCurveKem(curve: ECDSA, scalarLen: number, elemLen: number, nseed: number): TRet<KEM> {\n const Fn = curve.Point.Fn;\n if (!Fn) throw new Error('no Point.Fn');\n // Scan scalar-sized windows until one decodes to a nonzero scalar in `[1, n-1]`; if every\n // window is zero or out of range, fail instead of silently reducing modulo `n`.\n function rejectionSampling(seed: TArg<Uint8Array>): TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }> {\n let sk: bigint;\n for (let start = 0, end = scalarLen; ; start = end, end += scalarLen) {\n if (end > seed.length) throw new Error('rejection sampling failed');\n sk = Fn.fromBytes(seed.subarray(start, end), true);\n if (Fn.isValidNot0(sk)) break;\n }\n const secretKey = Fn.toBytes(Fn.create(sk));\n const publicKey = curve.getPublicKey(secretKey, false);\n return { secretKey, publicKey } as TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }>;\n }\n\n return {\n lengths: {\n secretKey: scalarLen,\n publicKey: elemLen,\n seed: nseed,\n msg: nseed,\n cipherText: elemLen,\n },\n keygen(seed: TArg<Uint8Array> = randomBytes(nseed)) {\n abytes(seed, nseed, 'seed');\n return rejectionSampling(seed);\n },\n getPublicKey(secretKey: TArg<Uint8Array>) {\n return curve.getPublicKey(secretKey, false) as TRet<Uint8Array>;\n },\n encapsulate(publicKey: TArg<Uint8Array>, rand: TArg<Uint8Array> = randomBytes(nseed)) {\n abytes(rand, nseed, 'rand');\n let ek: Uint8Array | undefined = undefined;\n try {\n ek = rejectionSampling(rand).secretKey;\n const sharedSecret = this.decapsulate(publicKey, ek);\n const cipherText = curve.getPublicKey(ek, false) as TRet<Uint8Array>;\n return { sharedSecret, cipherText };\n } finally {\n // Rejection-sampled NIST-curve ephemeral secret keys are temporary encapsulation state and\n // must be wiped even if peer-key validation or shared-secret derivation throws.\n if (ek) cleanBytes(ek);\n }\n },\n decapsulate(cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) {\n const full = curve.getSharedSecret(secretKey, cipherText);\n return full.subarray(1) as TRet<Uint8Array>;\n },\n };\n}\n\n/**\n * Internal ML-KEM + NIST-curve combiner.\n * `nseed` controls only the curve-side rejection-sampling budget; it is expanded from the\n * 32-byte root seed and is not itself part of the exported secret-key length.\n * The domain-separation `label` is used only in the final `sha3_256` combiner, not in\n * `shake256(seed, { dkLen: 64 + nseed })`,\n * and the combiner hashes `ss0 || ss1 || ct1 || pk1 || label`.\n */\nfunction concreteHybridKem(\n label: string,\n mlkem: TArg<KEM>,\n curve: ECDSA,\n nseed: number\n): TRet<KEM> {\n const { secretKey: scalarLen, publicKeyUncompressed: elemLen } = curve.lengths;\n if (!scalarLen || !elemLen) throw new Error('wrong curve');\n const curveKem = nistCurveKem(curve, scalarLen, elemLen, nseed);\n const mlkemSeedLen = 64;\n const totalSeedLen = mlkemSeedLen + nseed;\n\n return combineKEMS(\n 32,\n 32,\n (seed: TArg<Uint8Array>): TRet<Uint8Array> => {\n abytes(seed, 32);\n const expanded = shake256(seed, { dkLen: totalSeedLen });\n const mlkemSeed = expanded.subarray(0, mlkemSeedLen);\n const curveSeed = expanded.subarray(mlkemSeedLen, totalSeedLen);\n return concatBytes(mlkemSeed, curveSeed) as TRet<Uint8Array>;\n },\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes(label))),\n mlkem,\n curveKem\n );\n}\n\n/** P-256 + ML-KEM-768 hybrid preset. */\nexport const ml_kem768_p256: TRet<KEM> = /* @__PURE__ */ (() =>\n concreteHybridKem('MLKEM768-P256', ml_kem768, p256, 128))();\n\n/** P-384 + ML-KEM-1024 hybrid preset. */\nexport const ml_kem1024_p384: TRet<KEM> = /* @__PURE__ */ (() =>\n concreteHybridKem('MLKEM1024-P384', ml_kem1024, p384, 48))();\n\n// Legacy aliases\n/** Legacy alias for `ml_kem768_x25519`. */\nexport const XWing: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_x25519)();\n/** Legacy alias for `ml_kem768_x25519`. */\nexport const MLKEM768X25519: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_x25519)();\n/** Legacy alias for `ml_kem768_p256`. */\nexport const MLKEM768P256: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_p256)();\n/** Legacy alias for `ml_kem1024_p384`. */\nexport const MLKEM1024P384: TRet<KEM> = /* @__PURE__ */ (() => ml_kem1024_p384)();\n/** Legacy alias for `QSF_ml_kem768_p256`. */\nexport const QSFMLKEM768P256: TRet<KEM> = /* @__PURE__ */ (() => QSF_ml_kem768_p256)();\n/** Legacy alias for `QSF_ml_kem1024_p384`. */\nexport const QSFMLKEM1024P384: TRet<KEM> = /* @__PURE__ */ (() => QSF_ml_kem1024_p384)();\n/** Legacy alias for `KitchenSink_ml_kem768_x25519`. */\nexport const KitchenSinkMLKEM768X25519: TRet<KEM> = /* @__PURE__ */ (() =>\n KitchenSink_ml_kem768_x25519)();\n","import { hkdf } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nexport interface HkdfSha256Opts {\n readonly ikm: Uint8Array;\n readonly salt: Uint8Array;\n readonly info: Uint8Array;\n readonly length: number;\n}\n\nexport function hkdfSha256(opts: HkdfSha256Opts): Uint8Array {\n return hkdf(sha256, opts.ikm, opts.salt, opts.info, opts.length);\n}\n","import { XWing } from '@noble/post-quantum/hybrid.js';\n\n// X-Wing (ML-KEM-768 + X25519) hybrid KEM per draft-connolly-cfrg-xwing-kem-10.\n// `XWing` is @noble/post-quantum's alias for `ml_kem768_x25519`. We expose it\n// through opts-object wrappers that pin the wire lengths and map noble's field\n// names onto the project's vocabulary.\n//\n// Unlike the bare X25519 KEM, there is no contributory-behaviour rejection to\n// translate: X-Wing combines the ML-KEM and X25519 shared secrets through a\n// SHA3-256 combiner that also binds the X25519 ephemeral and recipient public\n// keys, and ML-KEM's implicit rejection already yields a constant-work\n// pseudorandom secret on a malformed ciphertext. Decapsulation therefore never\n// throws on attacker-supplied wire data — a wrong shared secret is the correct,\n// indistinguishable failure mode, and callers MUST treat it as a non-match\n// rather than expecting an exception.\n\nexport const MLKEM768X25519_PUBLIC_KEY_LENGTH = 1216 as const;\nexport const MLKEM768X25519_ENC_LENGTH = 1120 as const;\nexport const MLKEM768X25519_SHARED_SECRET_LENGTH = 32 as const;\nexport const MLKEM768X25519_SEED_LENGTH = 32 as const;\nexport const MLKEM768X25519_ESEED_LENGTH = 64 as const;\n\nexport interface Mlkem768X25519KeyPair {\n // The 32-byte root seed IS the secret key: the ML-KEM coins and the X25519\n // scalar are re-expanded from it via SHAKE-256 at decapsulation. (Later X-Wing\n // drafts also define an optional expanded decapsulation-key form; we keep the\n // seed-only key, which the draft-10 Appendix C vectors still pin.)\n readonly secretSeed: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface Mlkem768X25519EncapsulateOpts {\n readonly publicKey: Uint8Array;\n // Optional 64-byte encapsulation randomness (msgRand). When supplied the\n // ciphertext and shared secret are fully deterministic; a 32-byte value is\n // rejected by noble, so we pin the length here too.\n readonly eseed?: Uint8Array;\n}\n\nexport interface Mlkem768X25519Encapsulation {\n readonly enc: Uint8Array;\n readonly ss: Uint8Array;\n}\n\nexport interface Mlkem768X25519DecapsulateOpts {\n readonly secretSeed: Uint8Array;\n readonly enc: Uint8Array;\n}\n\nexport function mlkem768x25519Keygen(seed: Uint8Array): Mlkem768X25519KeyPair {\n if (seed.length !== MLKEM768X25519_SEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 seed must be ${MLKEM768X25519_SEED_LENGTH} bytes, got ${seed.length}`,\n );\n }\n const { secretKey, publicKey } = XWing.keygen(seed);\n return { secretSeed: secretKey, publicKey };\n}\n\nexport function mlkem768x25519Encapsulate(\n opts: Mlkem768X25519EncapsulateOpts,\n): Mlkem768X25519Encapsulation {\n if (opts.publicKey.length !== MLKEM768X25519_PUBLIC_KEY_LENGTH) {\n throw new Error(\n `mlkem768x25519 public key must be ${MLKEM768X25519_PUBLIC_KEY_LENGTH} bytes, got ${opts.publicKey.length}`,\n );\n }\n if (opts.eseed !== undefined && opts.eseed.length !== MLKEM768X25519_ESEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 eseed must be ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${opts.eseed.length}`,\n );\n }\n const { cipherText, sharedSecret } = XWing.encapsulate(opts.publicKey, opts.eseed);\n return { enc: cipherText, ss: sharedSecret };\n}\n\nexport function mlkem768x25519Decapsulate(opts: Mlkem768X25519DecapsulateOpts): Uint8Array {\n // Pre-check both lengths before calling noble: decapsulation must perform a\n // constant amount of work for any caller-supplied ciphertext (implicit\n // rejection), which requires the inputs to be the exact expected sizes.\n if (opts.secretSeed.length !== MLKEM768X25519_SEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 secret seed must be ${MLKEM768X25519_SEED_LENGTH} bytes, got ${opts.secretSeed.length}`,\n );\n }\n if (opts.enc.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new Error(\n `mlkem768x25519 enc must be ${MLKEM768X25519_ENC_LENGTH} bytes, got ${opts.enc.length}`,\n );\n }\n // noble's signature is decapsulate(cipherText, secretKey) — ciphertext first.\n return XWing.decapsulate(opts.enc, opts.secretSeed);\n}\n","import { x25519 } from '@noble/curves/ed25519.js';\n\n// RFC 7748 §6.1 contributory-behaviour rejection: a small-order (low-order)\n// Montgomery `u` coordinate makes the X25519 shared secret all-zero, which\n// @noble/curves refuses with `Error: invalid private or public key received`.\n// We rethrow that as a *typed* error so callers can distinguish a structurally\n// valid-but-malicious peer public key (a property of attacker-supplied wire\n// data — trial-decrypt MUST treat the slot as a non-match, not crash) from\n// genuine caller misuse such as a wrong-length key (which @noble raises as a\n// RangeError and which we deliberately let propagate untouched).\nexport class X25519LowOrderPointError extends Error {\n readonly code = 'X25519_LOW_ORDER_POINT' as const;\n constructor(options?: { cause?: unknown }) {\n super('x25519 ECDH rejected: peer public key is a small-order point', options);\n this.name = 'X25519LowOrderPointError';\n }\n}\n\n// @noble/curves v2 signals a small-order/all-zero shared secret with this exact\n// message. Matching on it (rather than the broad Error class) keeps unrelated\n// failures — e.g. a future internal assertion — surfacing as themselves.\nconst NOBLE_LOW_ORDER_MESSAGE = 'invalid private or public key received';\n\nexport interface X25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface X25519PublicKeyOpts {\n readonly secretKey: Uint8Array;\n}\n\nexport interface X25519EcdhOpts {\n readonly secretKey: Uint8Array;\n readonly theirPublicKey: Uint8Array;\n}\n\nexport function x25519Keygen(): X25519KeyPair {\n return x25519.keygen();\n}\n\nexport function x25519PublicKey(opts: X25519PublicKeyOpts): Uint8Array {\n return x25519.getPublicKey(opts.secretKey);\n}\n\nexport function x25519Ecdh(opts: X25519EcdhOpts): Uint8Array {\n try {\n return x25519.getSharedSecret(opts.secretKey, opts.theirPublicKey);\n } catch (e) {\n // Translate ONLY the contributory-check rejection into our typed error.\n // A wrong-length key throws a RangeError from @noble's length assertion;\n // that is caller misuse, not malicious wire data, so it must propagate.\n if (e instanceof Error && e.message === NOBLE_LOW_ORDER_MESSAGE) {\n throw new X25519LowOrderPointError({ cause: e });\n }\n throw e;\n }\n}\n","import * as ed from '@noble/ed25519';\nimport { sha512 } from '@noble/hashes/sha2.js';\n\ned.hashes.sha512 = sha512;\n\n// Ed25519 group order L (= 2^252 + 27742317777372353535851937790883648493).\nconst L = ed.Point.CURVE().n;\n\nexport interface SignEd25519Opts {\n readonly seed: Uint8Array;\n readonly message: Uint8Array;\n}\n\nexport interface VerifyEd25519Opts {\n readonly publicKey: Uint8Array;\n readonly message: Uint8Array;\n readonly signature: Uint8Array;\n}\n\nexport interface GetPublicKeyEd25519Opts {\n readonly seed: Uint8Array;\n}\n\nexport function signEd25519(opts: SignEd25519Opts): Uint8Array {\n return ed.sign(opts.message, opts.seed);\n}\n\n// Little-endian 32-byte scalar → bigint.\nfunction leBytesToBigInt(bytes: Uint8Array): bigint {\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) {\n value = (value << 8n) | BigInt(bytes[i]!);\n }\n return value;\n}\n\n// Strict (non-cofactored) Ed25519 verification per RFC 8032 §5.1.7, matching\n// libsodium/PyNaCl `crypto_sign_verify_detached` and ed25519-dalek\n// `verify_strict`. The cofactor-less check rejects every small-order /\n// torsion-component edge case in the C2SP/CCTV corpus, which noble's\n// `{ zip215: false }` mode does NOT (it remains cofactored: it checks\n// `[8]([S]B - [k]A - R) == 0`, accepting torsion components).\n//\n// The verification equation is the unscaled `[S]B == R + [k]A`, rewritten as\n// `[S]B - [k]A - R == identity`. We reject S >= L (non-canonical scalar) and\n// any small-order A or R up front, so a torsion component can never be smuggled\n// through the cofactor multiplication the cofactored variant performs.\nexport function verifyEd25519(opts: VerifyEd25519Opts): boolean {\n const { signature, message, publicKey } = opts;\n if (signature.length !== 64 || publicKey.length !== 32) return false;\n\n // S = LE(sig[32..64]); reject if not a canonical scalar (S >= L).\n const S = leBytesToBigInt(signature.subarray(32, 64));\n if (S >= L) return false;\n\n // Decode A (public key) and R (sig[0..32]) with the canonical (non-zip215)\n // point encoding; a non-canonical encoding throws and rejects.\n let A: ed.Point;\n let R: ed.Point;\n try {\n A = ed.Point.fromBytes(publicKey);\n R = ed.Point.fromBytes(signature.subarray(0, 32));\n } catch {\n return false;\n }\n\n // Reject small-order (cofactor-torsion) A or R: this is exactly the strictness\n // that distinguishes verify_strict from the cofactored check.\n if (A.isSmallOrder() || R.isSmallOrder()) return false;\n\n // k = SHA-512(R || A || M) reduced mod L.\n const k =\n leBytesToBigInt(ed.hash(concatBytes(signature.subarray(0, 32), publicKey, message))) % L;\n\n // Accept iff [S]B - [k]A - R == identity. `multiplyUnsafe` returns the\n // identity for a 0 scalar, but guard explicitly to avoid relying on that.\n const sB = S === 0n ? ed.Point.ZERO : ed.Point.BASE.multiplyUnsafe(S);\n const kA = k === 0n ? ed.Point.ZERO : A.multiplyUnsafe(k);\n return sB.subtract(kA).subtract(R).is0();\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += p.length;\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nexport function getPublicKeyEd25519(opts: GetPublicKeyEd25519Opts): Uint8Array {\n return ed.getPublicKey(opts.seed);\n}\n","export type SeedDeriveErrorCode = 'INVALID_SEED_LENGTH';\n\nexport class SeedDeriveError extends Error {\n readonly code: SeedDeriveErrorCode;\n\n constructor(code: SeedDeriveErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'SeedDeriveError';\n this.code = code;\n }\n}\n","import { hkdfSha256 } from '../kdf/hkdf';\nimport { mlkem768x25519Keygen } from '../kem/mlkem768x25519';\nimport { x25519PublicKey } from '../kem/x25519';\nimport { getPublicKeyEd25519 } from '../sig/ed25519';\n\nimport { SeedDeriveError } from './errors';\n\n// HKDF info constants for the long-term identity keypairs.\n// These literal byte sequences are part of the on-wire protocol; every\n// conformant implementation MUST hash against these exact ASCII bytes (the\n// Python parity twin pins the identical labels).\nexport const INFO_ED25519: Uint8Array = new TextEncoder().encode('cardano-poe-ed25519-v1');\nexport const INFO_X25519: Uint8Array = new TextEncoder().encode('cardano-poe-x25519-v1');\nexport const INFO_MLKEM768X25519: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-mlkem768x25519-v1',\n);\n\nif (INFO_ED25519.length !== 22) {\n throw new Error('INFO_ED25519 byte-length invariant violated (expected 22)');\n}\nif (INFO_X25519.length !== 21) {\n throw new Error('INFO_X25519 byte-length invariant violated (expected 21)');\n}\nif (INFO_MLKEM768X25519.length !== 29) {\n throw new Error('INFO_MLKEM768X25519 byte-length invariant violated (expected 29)');\n}\n\nconst EMPTY_SALT: Uint8Array = new Uint8Array(0);\nconst SEED_LENGTH = 32;\nconst DERIVED_LENGTH = 32;\n\nexport interface DerivedEd25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface DerivedX25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface DerivedMlKem768X25519KeyPair {\n readonly secretSeed: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nfunction assertSeedLength(seed: Uint8Array): void {\n if (seed.length !== SEED_LENGTH) {\n throw new SeedDeriveError(\n 'INVALID_SEED_LENGTH',\n `seed must be exactly 32 bytes, got ${seed.length}`,\n );\n }\n}\n\nexport function deriveEd25519KeypairFromSeed(seed: Uint8Array): DerivedEd25519KeyPair {\n assertSeedLength(seed);\n const secretKey = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_ED25519,\n length: DERIVED_LENGTH,\n });\n const publicKey = getPublicKeyEd25519({ seed: secretKey });\n return { secretKey, publicKey };\n}\n\nexport function deriveX25519KeypairFromSeed(seed: Uint8Array): DerivedX25519KeyPair {\n assertSeedLength(seed);\n const secretKey = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_X25519,\n length: DERIVED_LENGTH,\n });\n const publicKey = x25519PublicKey({ secretKey });\n return { secretKey, publicKey };\n}\n\nexport function deriveMlKem768X25519KeypairFromSeed(\n seed: Uint8Array,\n): DerivedMlKem768X25519KeyPair {\n assertSeedLength(seed);\n // The 32-byte HKDF output IS the X-Wing root seed: keygen re-expands the\n // ML-KEM coins and the X25519 scalar from it, so the derived keypair's\n // secretSeed equals this value.\n const xwingSeed = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_MLKEM768X25519,\n length: DERIVED_LENGTH,\n });\n return mlkem768x25519Keygen(xwingSeed);\n}\n","// Minimal BIP-173 bech32 encoder used to format age-style recipient strings.\n//\n// This package's dependency policy keeps the runtime import graph to a small,\n// audited set of cryptographic libraries, so we inline the exact bech32\n// algorithm here rather than pull in a general-purpose base-encoding library.\n// Output is byte-identical to the no-length-limit form of a standard bech32\n// encoder (`encode(hrp, toWords(bytes))` with the 90-char BIP-173 cap\n// disabled): age recipients exceed that cap — an X-Wing recipient is ~1960\n// characters — so the limit must be off.\n\nconst BECH32_ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nconst ENCODING_CONST = 1; // BIP-173 bech32 (not bech32m).\n\nfunction polymodStep(pre: number): number {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1) chk ^= POLYMOD_GENERATORS[i]!;\n }\n return chk;\n}\n\n// 8-bit bytes → 5-bit words, padding the final partial group with zero bits.\nfunction bytesToWords(bytes: Uint8Array): number[] {\n const words: number[] = [];\n let carry = 0;\n let pos = 0;\n const mask = (1 << 5) - 1;\n for (const n of bytes) {\n carry = (carry << 8) | n;\n pos += 8;\n for (; pos >= 5; pos -= 5) words.push((carry >> (pos - 5)) & mask);\n carry &= (1 << pos) - 1;\n }\n if (pos > 0) words.push((carry << (5 - pos)) & mask);\n return words;\n}\n\nfunction checksum(prefix: string, words: number[]): string {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error(`bech32: invalid prefix (${prefix})`);\n chk = polymodStep(chk) ^ (c >> 5);\n }\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n for (let i = 0; i < 6; i++) chk = polymodStep(chk);\n chk ^= ENCODING_CONST;\n let out = '';\n for (let i = 0; i < 6; i++) out += BECH32_ALPHABET[(chk >> (5 * (5 - i))) & 31];\n return out;\n}\n\n// Encode raw bytes to a bech32 string with NO length limit. `prefix` is the HRP.\nexport function bech32EncodeNoLimit(prefix: string, bytes: Uint8Array): string {\n if (prefix.length === 0) throw new Error('bech32: empty prefix');\n const words = bytesToWords(bytes);\n let payload = '';\n for (const w of words) payload += BECH32_ALPHABET[w];\n const lowered = prefix.toLowerCase();\n return `${lowered}1${payload}${checksum(lowered, words)}`;\n}\n\n// Recompute the polymod over the HRP + every data word (the trailing six being\n// the checksum) and test it against the encoding constant. True iff the string\n// carries a valid bech32 checksum.\nfunction checksumValid(prefix: string, words: number[]): boolean {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) >> 5);\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n return chk === ENCODING_CONST;\n}\n\n// 5-bit words → 8-bit bytes (the inverse of `bytesToWords`). Rejects\n// non-canonical padding: any leftover must be fewer than 5 bits and all zero,\n// matching the zero-fill `bytesToWords` applies to a final partial group.\nfunction wordsToBytes(words: number[]): Uint8Array {\n const out: number[] = [];\n let carry = 0;\n let pos = 0;\n for (const w of words) {\n carry = (carry << 5) | w;\n pos += 5;\n for (; pos >= 8; pos -= 8) out.push((carry >> (pos - 8)) & 0xff);\n carry &= (1 << pos) - 1;\n }\n if (pos >= 5 || carry !== 0) throw new Error('bech32: non-canonical padding');\n return Uint8Array.from(out);\n}\n\n// Decode a bech32 string with NO length limit, verifying the checksum. Returns\n// the lower-cased HRP and the decoded data bytes. The inverse of\n// `bech32EncodeNoLimit`. The separator is the last `1` in the string, so HRPs\n// that themselves contain a `1` (e.g. the `age1pqc` recipient prefix) round-trip\n// correctly.\nexport function bech32DecodeNoLimit(input: string): { hrp: string; bytes: Uint8Array } {\n if (input.length === 0) throw new Error('bech32: empty string');\n const hasLower = input !== input.toUpperCase();\n const hasUpper = input !== input.toLowerCase();\n if (hasLower && hasUpper) throw new Error('bech32: mixed-case string');\n const s = input.toLowerCase();\n const sep = s.lastIndexOf('1');\n if (sep < 1) throw new Error('bech32: missing human-readable prefix');\n if (s.length - sep - 1 < 6) throw new Error('bech32: data too short for checksum');\n const hrp = s.slice(0, sep);\n for (let i = 0; i < hrp.length; i++) {\n const c = hrp.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error('bech32: invalid prefix character');\n }\n const words: number[] = [];\n for (let i = sep + 1; i < s.length; i++) {\n const v = BECH32_ALPHABET.indexOf(s[i]!);\n if (v === -1) throw new Error('bech32: invalid data character');\n words.push(v);\n }\n if (!checksumValid(hrp, words)) throw new Error('bech32: bad checksum');\n return { hrp, bytes: wordsToBytes(words.slice(0, words.length - 6)) };\n}\n","// Encodes a raw KEM public key to a bech32 age-style recipient string — the\n// form a sender uses to address a sealed PoE record.\n//\n// • X25519 (32 bytes) → \"age1…\"\n// • X-Wing / ML-KEM-768 + X25519 (1216 bytes) → \"age1pqc…\"\n//\n// The two HRPs make a recipient self-describing: a parser routes to the right\n// KEM purely from the bech32 prefix. We use the `age1pqc` HRP for the hybrid\n// key (upstream age v1.3.0 claims the shorter `age1pq` HRP for the same X-Wing\n// primitive; `age1pqc` avoids colliding with that wire identifier).\n//\n// The X-Wing public key derives for free from the same identity seed via\n// `deriveMlKem768X25519KeypairFromSeed`, so every identity always has one and\n// can RECEIVE hybrid sealed records even when it publishes via the classical\n// X25519 path.\n\nimport { bech32DecodeNoLimit, bech32EncodeNoLimit } from './bech32';\n\nconst X25519_HRP = 'age';\nconst XWING_HRP = 'age1pqc';\nconst X25519_PUBLIC_KEY_BYTES = 32;\nconst XWING_PUBLIC_KEY_BYTES = 1216;\n\n// The KEM a recipient string addresses, inferred from its bech32 HRP.\nexport type RecipientKem = 'x25519' | 'mlkem768x25519';\n\nexport interface ParsedAgeRecipient {\n readonly kem: RecipientKem;\n readonly publicKey: Uint8Array;\n}\n\nexport function encodeAgeX25519Recipient(publicKey: Uint8Array): string {\n if (publicKey.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeX25519Recipient: publicKey must be exactly 32 bytes');\n }\n return bech32EncodeNoLimit(X25519_HRP, publicKey);\n}\n\nexport function encodeAgeXWingRecipient(publicKey: Uint8Array): string {\n if (publicKey.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeXWingRecipient: publicKey must be exactly 1216 bytes');\n }\n return bech32EncodeNoLimit(XWING_HRP, publicKey);\n}\n\n// Decode an age-style recipient string back to its raw KEM public key, routing\n// on the bech32 HRP. The inverse of `encodeAgeX25519Recipient` /\n// `encodeAgeXWingRecipient`: a sender can take a recipient string a peer shared\n// and recover the exact public key (and which KEM it belongs to) needed to seal\n// a record to them. Surrounding whitespace is tolerated so pasted strings parse.\n// Throws on an unknown HRP, a bad checksum, or a key length that does not match\n// the HRP's KEM.\nexport function parseAgeRecipient(recipient: string): ParsedAgeRecipient {\n if (typeof recipient !== 'string') {\n throw new Error('parseAgeRecipient: recipient must be a string');\n }\n const { hrp, bytes } = bech32DecodeNoLimit(recipient.trim());\n if (hrp === X25519_HRP) {\n if (bytes.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age recipient must carry a 32-byte X25519 key');\n }\n return { kem: 'x25519', publicKey: bytes };\n }\n if (hrp === XWING_HRP) {\n if (bytes.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age1pqc recipient must carry a 1216-byte X-Wing key');\n }\n return { kem: 'mlkem768x25519', publicKey: bytes };\n }\n throw new Error(`parseAgeRecipient: unrecognized recipient prefix \"${hrp}\"`);\n}\n","export class AeadVerificationError extends Error {\n readonly code: string = 'aead_verification_failed';\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'AeadVerificationError';\n }\n}\n","import { chacha20poly1305 } from '@noble/ciphers/chacha.js';\n\nimport { AeadVerificationError } from './errors';\n\nexport interface ChaCha20Poly1305EncryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly plaintext: Uint8Array;\n}\n\nexport interface ChaCha20Poly1305DecryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly ciphertext: Uint8Array;\n}\n\nexport function chacha20Poly1305Encrypt(opts: ChaCha20Poly1305EncryptOpts): Uint8Array {\n return chacha20poly1305(opts.key, opts.nonce, opts.aad).encrypt(opts.plaintext);\n}\n\nexport function chacha20Poly1305Decrypt(opts: ChaCha20Poly1305DecryptOpts): Uint8Array {\n try {\n return chacha20poly1305(opts.key, opts.nonce, opts.aad).decrypt(opts.ciphertext);\n } catch (cause) {\n throw new AeadVerificationError('chacha20-poly1305 decrypt failed', { cause });\n }\n}\n","import { xchacha20poly1305 } from '@noble/ciphers/chacha.js';\n\nimport { AeadVerificationError } from './errors';\n\nexport interface XChaCha20Poly1305EncryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly plaintext: Uint8Array;\n}\n\nexport interface XChaCha20Poly1305DecryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly ciphertext: Uint8Array;\n}\n\nexport function xchacha20Poly1305Encrypt(opts: XChaCha20Poly1305EncryptOpts): Uint8Array {\n return xchacha20poly1305(opts.key, opts.nonce, opts.aad).encrypt(opts.plaintext);\n}\n\nexport function xchacha20Poly1305Decrypt(opts: XChaCha20Poly1305DecryptOpts): Uint8Array {\n try {\n return xchacha20poly1305(opts.key, opts.nonce, opts.aad).decrypt(opts.ciphertext);\n } catch (cause) {\n throw new AeadVerificationError('xchacha20-poly1305 decrypt failed', { cause });\n }\n}\n","// Sealed-PoE error taxonomy (wire-shape + partitioning-oracle pre-checks).\n\nexport type EciesSealedPoeErrorCode =\n | 'ENC_SLOTS_EMPTY'\n | 'ENC_SLOTS_REQUIRED'\n | 'ENC_SLOTS_MAC_REQUIRED'\n | 'ENC_SLOTS_MAC_INVALID_LENGTH'\n | 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL'\n | 'ENC_SLOTS_TOO_MANY'\n | 'ENC_ENVELOPE_TOO_LARGE'\n | 'KEM_EPK_LENGTH_MISMATCH'\n | 'KEM_CT_LENGTH_MISMATCH'\n | 'INVALID_CEK_LENGTH'\n | 'NONCE_LENGTH_MISMATCH'\n | 'INVALID_EPHEMERAL_SECRET_LENGTH'\n | 'EPHEMERAL_SECRETS_COUNT_MISMATCH'\n | 'UNSUPPORTED_ENC_VERSION'\n | 'UNSUPPORTED_AEAD_ALG'\n | 'UNSUPPORTED_KEM_ALG'\n | 'INVALID_ENVELOPE_SHAPE'\n | 'INVALID_RECIPIENT_KEY'\n | 'WRAP_LENGTH_MISMATCH';\n\nexport class EciesSealedPoeError extends Error {\n readonly code: EciesSealedPoeErrorCode;\n\n constructor(code: EciesSealedPoeErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'EciesSealedPoeError';\n this.code = code;\n }\n}\n","// Single source of truth for two seams that wrap, unwrap, and the wire encoder\n// MUST agree on byte-for-byte:\n//\n// 1. How the 1120-byte X-Wing `enc` is split into the ≤ 64-byte byte-string\n// chunks the Cardano ledger requires (`kem_ct`), and the inverse join.\n// 2. The canonical slot-array structure the slots transcript commits to.\n//\n// Keeping both here means the producer (wrap) and the verifier (unwrap), as well\n// as the downstream record encoder, cannot diverge on the bytes the slot-set MAC\n// commits to — the single highest correctness risk for the hybrid branch, since\n// a divergence would leave the ML-KEM ciphertext unauthenticated.\n\nimport type { CanonicalCborValue } from '../cbor/canonical';\n\nimport type { Mlkem768X25519Slot, X25519Slot } from './wrap';\n\n// The envelope-level KEM discriminator.\nexport type SealedKem = 'x25519' | 'mlkem768x25519';\n\n// Cardano ledger CDDL caps every `transaction_metadatum` byte string at 64\n// bytes, so any value larger than 64 bytes is carried as an array of ≤ 64-byte\n// chunks (the `bytes-chunk-array` wire form). This is the identical split rule\n// the record encoder applies to chunked COSE bytes.\nconst CHUNK_MAX_BYTES = 64;\n\n// Split a logical byte string into ≤ 64-byte chunks. Used for the X-Wing\n// `enc` → `kem_ct` wire form. Subarrays are views over the input, never copies.\nexport function chunkKemCt(value: Uint8Array): Uint8Array[] {\n if (value.length === 0) {\n throw new Error('chunkKemCt: refusing to chunk an empty byte string');\n }\n const chunks: Uint8Array[] = [];\n for (let i = 0; i < value.length; i += CHUNK_MAX_BYTES) {\n chunks.push(value.subarray(i, Math.min(i + CHUNK_MAX_BYTES, value.length)));\n }\n return chunks;\n}\n\n// Inverse of chunkKemCt: concatenate the chunked `kem_ct` back into the flat\n// X-Wing `enc`. Performs NO length validation — the caller (unwrap) gates the\n// reassembled length against MLKEM768X25519_ENC_LENGTH before any decapsulation.\nexport function joinKemCt(chunks: ReadonlyArray<Uint8Array>): Uint8Array {\n let total = 0;\n for (const c of chunks) total += c.length;\n const out = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n out.set(c, offset);\n offset += c.length;\n }\n return out;\n}\n\n// KEM-driven canonical slot-array structure committed by the slots transcript.\n//\n// • x25519: each slot → { epk: bstr, wrap: bstr }\n// • mlkem768x25519: each slot → { kem_ct: [ bstr, ... ], wrap: bstr }\n//\n// The hybrid form re-chunks `kem_ct` into its canonical ≤ 64-byte sequence so\n// the transcript commits to the ciphertext BYTES, not the wire chunk boundaries.\n// The on-wire `kem_ct` array is a transport detail (the Cardano ledger's 64-byte\n// metadatum cap), and a hostile or non-canonical chunking ([1, 63, …] instead of\n// [64, …]) reassembles to the SAME bytes — so the commitment must be invariant to\n// it. Committing to the verbatim wire chunks would let an attacker re-chunk an\n// honest envelope and break the slots_mac match for an honest recipient. Honest\n// (already-64B-chunked) records are unchanged; a real byte flip still changes the\n// reassembled bytes and is still rejected.\n//\n// Returns the slot-array structure (NOT encoded) so the caller can embed it in\n// the larger slots-transcript map before a single canonical encode.\nexport function canonicalizeSlots(\n slots: ReadonlyArray<X25519Slot | Mlkem768X25519Slot>,\n kem: SealedKem,\n): CanonicalCborValue {\n if (kem === 'x25519') {\n return (slots as ReadonlyArray<X25519Slot>).map((s) => ({ epk: s.epk, wrap: s.wrap }));\n }\n return (slots as ReadonlyArray<Mlkem768X25519Slot>).map((s) => ({\n kem_ct: chunkKemCt(joinKemCt(s.kem_ct)),\n wrap: s.wrap,\n }));\n}\n","import { cdeDecodeOptions, decode, encode } from 'cbor2';\nimport { sortCoreDeterministic } from 'cbor2/sorts';\n\nimport { CanonicalCborError } from './errors';\n\nexport type CanonicalCborValue =\n | null\n | boolean\n | number\n | bigint\n | string\n | Uint8Array\n | readonly CanonicalCborValue[]\n | { readonly [key: string]: CanonicalCborValue }\n | ReadonlyMap<string | number, CanonicalCborValue>;\n\nexport function encodeCanonicalCbor(value: CanonicalCborValue): Uint8Array {\n return encode(value, {\n cde: true,\n collapseBigInts: true,\n rejectDuplicateKeys: true,\n sortKeys: sortCoreDeterministic,\n });\n}\n\nexport function decodeCanonicalCbor(bytes: Uint8Array): unknown {\n try {\n return decode(bytes, {\n ...cdeDecodeOptions,\n rejectStreaming: true,\n rejectDuplicateKeys: true,\n // A Label 309 record carries integers, byte/text strings, arrays, maps and\n // `null` — and nothing else. Without these rejections the major-type-7\n // surface leaks into the decoder: a float16/32/64 that happens to hold an\n // integral value (e.g. 1.0) silently decodes to the integer 1 and passes\n // a `z.literal(1)` / Number.isInteger schema check, so two byte strings\n // that are NOT byte-identical canonicalise to the same record. That\n // breaks the cross-implementation parity invariant (the Python twin\n // already rejects non-integer `v` / `enc.scheme` outright). Reject the\n // whole non-record surface — floats, negative zero, undefined, and\n // non-{true,false,null} simple values — so any such input surfaces as\n // MALFORMED_CBOR via mapDecodeError rather than decoding to a look-alike.\n rejectFloats: true,\n rejectNegativeZero: true,\n rejectUndefined: true,\n rejectSimple: true,\n });\n } catch (cause) {\n throw mapDecodeError(cause);\n }\n}\n\nfunction mapDecodeError(cause: unknown): CanonicalCborError {\n const message = cause instanceof Error ? cause.message : String(cause);\n const lower = message.toLowerCase();\n // Every canonical-decode violation collapses to the single public taxonomy\n // code MALFORMED_CBOR: indefinite-length (streaming) items, duplicate keys,\n // non-canonical (unsorted) key ordering, non-minimal integer encodings, and\n // invalid UTF-8 in text strings. cbor2 raises the SAME \"Duplicate or out of\n // order key\" message for both true duplicates AND distinct-but-unsorted keys,\n // so the two are indistinguishable by message — and per the Label 309 taxonomy\n // both belong under MALFORMED_CBOR anyway. The specific cause survives in the\n // human-readable message below; for indefinite-length we state it explicitly\n // so the diagnostic is not lost when the code is collapsed.\n const isIndefinite = lower.includes('streaming') || lower.includes('indefinite');\n const detail = isIndefinite\n ? `indefinite-length items are not permitted in canonical CBOR: ${message}`\n : message;\n return new CanonicalCborError('MALFORMED_CBOR', `cbor decode failed: ${detail}`, { cause });\n}\n","// Shared, byte-critical pieces of the slots-path sealed-PoE construction that\n// the producer (wrap) and every verifier (unwrap, trial-decrypt) MUST compute\n// byte-for-byte identically:\n//\n// 1. The slots transcript and its SHA-256 hash `slots_hash`.\n// 2. The content-AEAD additional-authenticated-data object `AD_CONTENT_SLOTS`.\n// 3. The content `payload_key` derivation from the CEK.\n// 4. The hybrid (X-Wing) per-slot KEK salt.\n// 5. The single-shot XChaCha20-Poly1305 maximum-payload guard.\n//\n// Keeping these in one module is the interop guarantee: a single divergence in\n// the canonical encoding silently yields a `slots_mac` or AEAD tag that another\n// implementation cannot reproduce, with no typed error to localise the fault.\n// There is exactly one shared implementation, imported by both sides.\n\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nimport { encodeCanonicalCbor, type CanonicalCborValue } from '../cbor/canonical';\nimport { hkdfSha256 } from '../kdf/hkdf';\n\nimport { canonicalizeSlots, type SealedKem } from './slots-codec';\nimport type { Mlkem768X25519Slot, X25519Slot } from './wrap';\n\n// Internal domain-separation labels. Each is exact ASCII with no terminator and\n// no length prefix; each is a fixed constant of the scheme, never serialised on\n// the wire and never registry-selectable. The byte-length invariants below keep\n// the SCREAMING_SNAKE constants in sync with the ASCII literals every conformant\n// verifier hashes against.\n\n// SHA-256 prefix for the slots-transcript hash `slots_hash`.\nexport const CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-slots-transcript-v1',\n);\n// HKDF info for the slots-path content `payload_key`.\nexport const CARDANO_POE_HKDF_INFO_PAYLOAD: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-payload-v1',\n);\n// HKDF info for the passphrase-path content `payload_key`.\nexport const CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-payload-passphrase-v1',\n);\n// SHA-256 prefix for the hybrid (X-Wing) per-slot KEK HKDF salt.\nexport const CARDANO_POE_XWING_KEK_SALT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-xwing-kek-salt-v1',\n);\n\nif (CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length !== 31) {\n throw new Error(\n 'CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX byte-length invariant violated (expected 31)',\n );\n}\nif (CARDANO_POE_HKDF_INFO_PAYLOAD.length !== 22) {\n throw new Error('CARDANO_POE_HKDF_INFO_PAYLOAD byte-length invariant violated (expected 22)');\n}\nif (CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE.length !== 33) {\n throw new Error(\n 'CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE byte-length invariant violated (expected 33)',\n );\n}\nif (CARDANO_POE_XWING_KEK_SALT_PREFIX.length !== 29) {\n throw new Error('CARDANO_POE_XWING_KEK_SALT_PREFIX byte-length invariant violated (expected 29)');\n}\n\n// Scheme-fixed constant pinning the passphrase normalization profile the CEK was\n// derived under. Fed into the passphrase-path AAD; never serialised on the wire.\nexport const CARDANO_POE_PW_NORM_PROFILE = 'cardano-poe-pw-norm-v1' as const;\n\n// Verifier-side resource bounds a public parser MUST enforce BEFORE invoking any\n// KEM/AEAD primitive, so a malformed envelope cannot drive unbounded work. Both\n// are deployment-pinned reference constants (not wire fields); deployments MAY\n// tighten them. They sit far above the ~16 KiB Cardano transaction-metadata\n// ceiling that bounds honest records, so a conformant record never trips them.\n//\n// • MAX_SLOTS — the maximum slot count; an envelope with more slots is\n// rejected outright.\n// • MAX_DECODED_ENVELOPE_BYTES — a backstop on the decoded envelope's\n// aggregate byte size (nonce + slots_mac + every per-slot wire field),\n// bounding the work even before the slot-count cap would.\nexport const MAX_SLOTS = 1024;\nexport const MAX_DECODED_ENVELOPE_BYTES = 65536;\n\n// XChaCha20-Poly1305 is a single-shot AEAD over the whole plaintext; its 32-bit\n// internal block counter bounds one (key, nonce) invocation at 2^32 64-byte\n// ChaCha20 blocks, the first of which is consumed by the Poly1305 one-time key.\n// MAX_SEALED_PLAINTEXT is therefore (2^32 - 1) * 64 = 2^38 - 64 bytes; a plaintext\n// at or above it risks a counter-overflow keystream collision and MUST be\n// rejected before the AEAD is invoked on either side. This constant is identical\n// across all conformant implementations.\nexport const MAX_SEALED_PLAINTEXT = 274877906880; // 2^38 - 64\n// Poly1305 appends a 16-byte tag, so the corresponding ciphertext bound is + 16.\nexport const MAX_SEALED_CIPHERTEXT = MAX_SEALED_PLAINTEXT + 16;\n\nif (MAX_SEALED_PLAINTEXT !== 2 ** 38 - 64) {\n throw new Error('MAX_SEALED_PLAINTEXT invariant violated (expected 2^38 - 64)');\n}\n\n// Reject a slots-path plaintext at or above the single-shot keystream capacity,\n// before any AEAD call. Thrown on the producer side.\nexport function assertPlaintextWithinBound(plaintextLength: number): void {\n if (plaintextLength >= MAX_SEALED_PLAINTEXT) {\n throw new SealedPayloadTooLargeError(\n `plaintext length ${plaintextLength} is at or above the maximum sealed payload size ${MAX_SEALED_PLAINTEXT}`,\n );\n }\n}\n\n// Reject a slots-/passphrase-path ciphertext at or above the single-shot bound,\n// before any AEAD open. Thrown on the verifier side. The ciphertext carries the\n// plaintext plus a 16-byte Poly1305 tag.\nexport function assertCiphertextWithinBound(ciphertextLength: number): void {\n if (ciphertextLength >= MAX_SEALED_CIPHERTEXT) {\n throw new SealedPayloadTooLargeError(\n `ciphertext length ${ciphertextLength} is at or above the maximum sealed ciphertext size ${MAX_SEALED_CIPHERTEXT}`,\n );\n }\n}\n\nexport class SealedPayloadTooLargeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SealedPayloadTooLargeError';\n }\n}\n\n// SHA-256(\"cardano-poe-slots-transcript-v1\" || canonicalEncode(SLOTS_TRANSCRIPT)).\n// SLOTS_TRANSCRIPT is the closed six-key map binding the cross-KEM header fields\n// (scheme, path, aead, kem, nonce) to the canonicalised slot set, so a relay\n// that flips any header field while leaving slot shapes valid yields a different\n// `slots_hash` and the MAC fails. Computed ONCE per envelope and held constant\n// across the recipient trial-decrypt loop. The map keys are a SET — their wire\n// order is fixed by the canonical-encode sort, never hand-arranged here.\nexport function computeSlotsHash(args: {\n kem: SealedKem;\n nonce: Uint8Array;\n slots: ReadonlyArray<X25519Slot | Mlkem768X25519Slot>;\n}): Uint8Array {\n const transcript: CanonicalCborValue = {\n scheme: 1,\n path: 'slots',\n aead: 'xchacha20-poly1305',\n kem: args.kem,\n nonce: args.nonce,\n slots: canonicalizeSlots(args.slots, args.kem),\n };\n const encoded = encodeCanonicalCbor(transcript);\n const message = new Uint8Array(CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length + encoded.length);\n message.set(CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX, 0);\n message.set(encoded, CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length);\n return sha256(message);\n}\n\n// canonicalEncode(AD_CONTENT_SLOTS): the closed seven-key content-AEAD AAD for\n// the slots path. It re-binds the slots-path header AND carries both `slots_hash`\n// (binding to the exact transcript) and `slots_mac` (tying the content layer to\n// the CEK-keyed MAC the recipient matched). Both are deliberate, not redundant.\nexport function adContentSlots(args: {\n kem: SealedKem;\n nonce: Uint8Array;\n slotsHash: Uint8Array;\n slotsMac: Uint8Array;\n}): Uint8Array {\n const ad: CanonicalCborValue = {\n scheme: 1,\n path: 'slots',\n aead: 'xchacha20-poly1305',\n kem: args.kem,\n nonce: args.nonce,\n slots_hash: args.slotsHash,\n slots_mac: args.slotsMac,\n };\n return encodeCanonicalCbor(ad);\n}\n\n// canonicalEncode(AD_CONTENT_PASSPHRASE): the closed content-AEAD AAD for the\n// passphrase path. It binds the passphrase KDF parameters into the content tag,\n// so tampering with `salt` or any `params` value after encryption changes the\n// AAD and makes the AEAD open fail. The `normalization` profile id is a\n// scheme-fixed constant pinned into the AAD, never serialised on the wire. There\n// is NO `kem` key on this path.\nexport function adContentPassphrase(args: {\n nonce: Uint8Array;\n passphrase: {\n alg: string;\n salt: Uint8Array;\n params: { m: number; t: number; p: number };\n };\n}): Uint8Array {\n const ad: CanonicalCborValue = {\n scheme: 1,\n path: 'passphrase',\n aead: 'xchacha20-poly1305',\n nonce: args.nonce,\n passphrase: {\n alg: args.passphrase.alg,\n salt: args.passphrase.salt,\n params: {\n m: args.passphrase.params.m,\n t: args.passphrase.params.t,\n p: args.passphrase.params.p,\n },\n normalization: CARDANO_POE_PW_NORM_PROFILE,\n },\n };\n return encodeCanonicalCbor(ad);\n}\n\n// Slots-path content key: HKDF-SHA-256(ikm=CEK, salt=nonce, info=payload-v1).\n// The content is encrypted under this leaf of the CEK, never under the CEK\n// directly, so the wrap layer and the content layer never key the same primitive\n// on the same bytes.\nexport function slotsPayloadKey(args: { cek: Uint8Array; nonce: Uint8Array }): Uint8Array {\n return hkdfSha256({\n ikm: args.cek,\n salt: args.nonce,\n info: CARDANO_POE_HKDF_INFO_PAYLOAD,\n length: 32,\n });\n}\n\n// Passphrase-path content key: HKDF-SHA-256(ikm=CEK, salt=nonce,\n// info=payload-passphrase-v1).\nexport function passphrasePayloadKey(args: { cek: Uint8Array; nonce: Uint8Array }): Uint8Array {\n return hkdfSha256({\n ikm: args.cek,\n salt: args.nonce,\n info: CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE,\n length: 32,\n });\n}\n\n// Hybrid (mlkem768x25519) per-slot KEK salt:\n// SHA-256(\"cardano-poe-xwing-kek-salt-v1\" || kem_ct || pub_R). `kem_ct` is the\n// REASSEMBLED 1120-byte X-Wing ciphertext (the kem_ct anchors the KEK to a\n// slot-unique value) and `pub_R` the 1216-byte X-Wing recipient public key\n// (binding the KEK to the specific recipient) — the same two bindings the\n// classical `epk || pub_R` salt provides, expressed through a fixed-length\n// SHA-256 digest because the hybrid inputs are oversized.\nexport function xwingKekSalt(args: { kemCt: Uint8Array; pubR: Uint8Array }): Uint8Array {\n const message = new Uint8Array(\n CARDANO_POE_XWING_KEK_SALT_PREFIX.length + args.kemCt.length + args.pubR.length,\n );\n let offset = 0;\n message.set(CARDANO_POE_XWING_KEK_SALT_PREFIX, offset);\n offset += CARDANO_POE_XWING_KEK_SALT_PREFIX.length;\n message.set(args.kemCt, offset);\n offset += args.kemCt.length;\n message.set(args.pubR, offset);\n return sha256(message);\n}\n","// Multi-recipient sealed-PoE wrap (age-style ECIES + AEAD-bound slots).\n// Wire-field names are fixed by the standard: scheme, aead, kem, nonce, slots, slots_mac.\n//\n// Two KEM branches share one envelope shape, discriminated on the envelope-level\n// `kem` field:\n//\n// • kem: 'x25519' — classical age-style ECIES. Per-slot epk(32) + wrap(48).\n// • kem: 'mlkem768x25519' — X-Wing hybrid (ML-KEM-768 + X25519). Per-slot the\n// 1120-byte X-Wing enc carried as a chunked byte-string\n// array (`kem_ct`) + wrap(48). No per-slot epk.\n//\n// The slot type is a discriminated union so every consumer is forced — at compile\n// time — to branch on the KEM before touching kem-specific fields.\n\nimport { randomBytes } from '@noble/ciphers/utils.js';\nimport { hmac } from '@noble/hashes/hmac.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nimport { chacha20Poly1305Encrypt } from '../aead/chacha20-poly1305';\nimport { xchacha20Poly1305Encrypt } from '../aead/xchacha20-poly1305';\nimport { hkdfSha256 } from '../kdf/hkdf';\nimport {\n mlkem768x25519Encapsulate,\n MLKEM768X25519_ENC_LENGTH,\n MLKEM768X25519_ESEED_LENGTH,\n MLKEM768X25519_PUBLIC_KEY_LENGTH,\n} from '../kem/mlkem768x25519';\nimport { x25519Ecdh, x25519PublicKey } from '../kem/x25519';\n\nimport { EciesSealedPoeError } from './errors';\nimport { chunkKemCt, type SealedKem } from './slots-codec';\nimport {\n adContentSlots,\n assertPlaintextWithinBound,\n computeSlotsHash,\n slotsPayloadKey,\n xwingKekSalt,\n} from './transcript';\n\n// HKDF info strings — fixed protocol labels for KEK derivation and the slot MAC.\n// Byte-length invariants enforce that the SCREAMING_SNAKE constants stay in sync\n// with the on-wire ASCII literals every conformant verifier hashes against.\nexport const CARDANO_POE_HKDF_INFO_KEK: Uint8Array = new TextEncoder().encode('cardano-poe-kek-v1');\n// Hybrid (X-Wing) per-slot KEK label. Distinct from the classical label so a\n// KEK derived under one KEM can never collide with the other. Reused verbatim as\n// the per-slot wrap AEAD AAD, exactly as the classical path reuses its own label.\nexport const CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-kek-mlkem768x25519-v1',\n);\nexport const CARDANO_POE_HKDF_INFO_SLOTS_MAC: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-slots-mac-v1',\n);\n\nconst ZERO_NONCE_12: Uint8Array = new Uint8Array(12);\nconst EMPTY_SALT: Uint8Array = new Uint8Array(0);\nconst X25519_PUBLIC_KEY_LENGTH = 32 as const;\nconst X25519_SECRET_KEY_LENGTH = 32 as const;\nconst CEK_LENGTH = 32 as const;\nconst NONCE_LENGTH = 24 as const;\nconst WRAP_LENGTH = 48 as const;\nconst SLOTS_MAC_LENGTH = 32 as const;\n\nif (CARDANO_POE_HKDF_INFO_KEK.length !== 18) {\n throw new Error('CARDANO_POE_HKDF_INFO_KEK byte-length invariant violated (expected 18)');\n}\nif (CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519.length !== 33) {\n throw new Error(\n 'CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 byte-length invariant violated (expected 33)',\n );\n}\nif (CARDANO_POE_HKDF_INFO_SLOTS_MAC.length !== 24) {\n throw new Error('CARDANO_POE_HKDF_INFO_SLOTS_MAC byte-length invariant violated (expected 24)');\n}\nif (ZERO_NONCE_12.length !== 12) {\n throw new Error('ZERO_NONCE_12 byte-length invariant violated (expected 12)');\n}\n\n// Classical per-slot wire shape: { epk: bstr(32), wrap: bstr(48) }.\nexport interface X25519Slot {\n readonly epk: Uint8Array;\n readonly wrap: Uint8Array;\n}\n\n// Hybrid per-slot wire shape: { kem_ct: [ bstr .size (1..64) ], wrap: bstr(48) }.\n// `kem_ct` is the 1120-byte X-Wing enc carried as a chunked byte-string array\n// (the Cardano ledger caps any single metadatum bstr at 64 bytes). There is NO\n// per-slot epk and NO per-slot kem field — the KEM identifier is hoisted to\n// envelope scope (every slot shares it).\nexport interface Mlkem768X25519Slot {\n readonly kem_ct: ReadonlyArray<Uint8Array>;\n readonly wrap: Uint8Array;\n}\n\n// Back-compat alias retired: callers branch on the envelope `kem` and use the\n// concrete slot type. The discriminated `SealedEnvelope` below is the only\n// shape consumers should depend on.\n\n// Sealed envelope wire shape (discriminated on `kem`).\nexport type SealedEnvelope =\n | {\n readonly scheme: 1;\n readonly aead: 'xchacha20-poly1305';\n readonly kem: 'x25519';\n readonly nonce: Uint8Array;\n readonly slots: ReadonlyArray<X25519Slot>;\n readonly slots_mac: Uint8Array;\n }\n | {\n readonly scheme: 1;\n readonly aead: 'xchacha20-poly1305';\n readonly kem: 'mlkem768x25519';\n readonly nonce: Uint8Array;\n readonly slots: ReadonlyArray<Mlkem768X25519Slot>;\n readonly slots_mac: Uint8Array;\n };\n\nexport interface SealedPoeOutput {\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n}\n\nexport interface WrapArgs {\n readonly plaintext: Uint8Array;\n readonly recipientPublicKeys: ReadonlyArray<Uint8Array>;\n // KEM branch selector. Defaults to 'x25519' for the classical path. The\n // recipient public-key length is validated against the chosen KEM.\n readonly kem?: SealedKem;\n readonly cek?: Uint8Array;\n readonly nonce?: Uint8Array;\n // Deterministic X25519 ephemeral scalars — x25519 branch only.\n readonly ephemeralSecrets?: ReadonlyArray<Uint8Array>;\n // Deterministic X-Wing encapsulation randomness (64 bytes each) — hybrid\n // branch only. One per recipient, parallel to recipientPublicKeys.\n readonly eseeds?: ReadonlyArray<Uint8Array>;\n readonly skipShuffle?: boolean;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n// Anonymity invariant: wire ordering MUST NOT encode \"primary\n// recipient first\". A CSPRNG-keyed Fisher-Yates shuffle uniformly permutes the\n// slot array so trial-decrypt order leaks no recipient identity. The\n// slot-set HMAC is computed AFTER this shuffle, binding the on-wire order.\n//\n// Draw an unbiased index in [0, m) from a CSPRNG uint32 via rejection sampling.\n// A plain `u32 % m` skews toward the low residues whenever `m` does not divide\n// 2^32 evenly: the values [0, 2^32 mod m) each occur one extra time. This\n// function exists purely to produce a UNIFORM permutation, so the bias — though\n// cryptographically negligible — is exactly the property we cannot tolerate.\n// We reject any draw landing in the final partial block [limit, 2^32) and\n// redraw, leaving only the residues that map uniformly onto [0, m).\n// Exported so the rejection-bound arithmetic can be asserted directly in tests\n// without relying on a flaky statistical-distribution check.\nexport function uniformIndexBelow(m: number): number {\n // 2^32 mod m, computed without overflowing the 32-bit space.\n const limit = 0x1_0000_0000 - (0x1_0000_0000 % m);\n const buf = new Uint32Array(1);\n let x: number;\n do {\n crypto.getRandomValues(buf);\n x = buf[0] as number;\n } while (x >= limit);\n return x % m;\n}\n\nfunction csprngShuffle<T>(arr: T[]): void {\n for (let i = arr.length - 1; i > 0; i--) {\n const j = uniformIndexBelow(i + 1);\n const tmp = arr[i] as T;\n arr[i] = arr[j] as T;\n arr[j] = tmp;\n }\n}\n\n// Wrap the CEK for one classical recipient: age-style ECIES stanza.\nfunction wrapSlotX25519(args: {\n pubR: Uint8Array;\n privEph: Uint8Array | undefined;\n cek: Uint8Array;\n slotIdx: number;\n}): X25519Slot {\n const privEph = args.privEph ?? randomBytes(X25519_SECRET_KEY_LENGTH);\n if (privEph.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_EPHEMERAL_SECRET_LENGTH',\n `ephemeralSecrets[${args.slotIdx}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${privEph.length}`,\n );\n }\n const epk = x25519PublicKey({ secretKey: privEph });\n const shared = x25519Ecdh({ secretKey: privEph, theirPublicKey: args.pubR });\n // age v1 stanza salt is `epk || pub_R`.\n const kek = hkdfSha256({\n ikm: shared,\n salt: concat(epk, args.pubR),\n info: CARDANO_POE_HKDF_INFO_KEK,\n length: 32,\n });\n // Per-slot wrap AAD MUST be the 18-byte ASCII literal of the KEK info\n // string (never empty AAD).\n const wrap = chacha20Poly1305Encrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK,\n plaintext: args.cek,\n });\n if (wrap.length !== WRAP_LENGTH) {\n throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);\n }\n return { epk, wrap };\n}\n\n// Wrap the CEK for one hybrid recipient: X-Wing encapsulation → HKDF → AEAD.\n// The KEK info label doubles as the wrap AEAD AAD, mirroring the classical path.\nfunction wrapSlotMlkem768X25519(args: {\n pubR: Uint8Array;\n eseed: Uint8Array | undefined;\n cek: Uint8Array;\n}): Mlkem768X25519Slot {\n const { enc, ss } = mlkem768x25519Encapsulate({\n publicKey: args.pubR,\n ...(args.eseed !== undefined ? { eseed: args.eseed } : {}),\n });\n if (enc.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new Error(`internal: enc.length=${enc.length}, expected ${MLKEM768X25519_ENC_LENGTH}`);\n }\n // The hybrid KEK salt binds the slot's own reassembled X-Wing ciphertext and\n // the recipient public key, mirroring the classical `epk || pub_R` salt: the\n // ciphertext anchors the KEK to a slot-unique value and `pub_R` binds it to\n // the specific recipient. It is computed outside the KEM, over the slot's wire\n // bytes, so it holds X-Wing as a black-box KEM.\n const kek = hkdfSha256({\n ikm: ss,\n salt: xwingKekSalt({ kemCt: enc, pubR: args.pubR }),\n info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n length: 32,\n });\n const wrap = chacha20Poly1305Encrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n plaintext: args.cek,\n });\n if (wrap.length !== WRAP_LENGTH) {\n throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);\n }\n return { kem_ct: chunkKemCt(enc), wrap };\n}\n\nexport function eciesSealedPoeWrap(args: WrapArgs): SealedPoeOutput {\n const { plaintext, recipientPublicKeys } = args;\n const kem: SealedKem = args.kem ?? 'x25519';\n const n = recipientPublicKeys.length;\n\n // Reject a plaintext at or above the single-shot keystream capacity before any\n // KEM or AEAD work, so an over-large input never reaches the content cipher.\n assertPlaintextWithinBound(plaintext.length);\n\n // There is no fixed upper bound on slot count; the producer SDK polices the\n // per-record byte budget. Only the lower bound is enforced here.\n if (n < 1) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_EMPTY',\n `recipientPublicKeys.length=${n} must be >= 1`,\n );\n }\n\n const expectedPubLen =\n kem === 'x25519' ? X25519_PUBLIC_KEY_LENGTH : MLKEM768X25519_PUBLIC_KEY_LENGTH;\n for (let i = 0; i < n; i++) {\n const pub = recipientPublicKeys[i];\n if (pub === undefined || pub.length !== expectedPubLen) {\n throw new EciesSealedPoeError(\n 'KEM_EPK_LENGTH_MISMATCH',\n `recipientPublicKeys[${i}] MUST be exactly ${expectedPubLen} bytes for kem='${kem}'`,\n );\n }\n }\n\n if (kem === 'x25519') {\n if (args.eseeds !== undefined) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n \"eseeds is an X-Wing (mlkem768x25519) override and MUST NOT be supplied for kem='x25519'\",\n );\n }\n if (args.ephemeralSecrets !== undefined && args.ephemeralSecrets.length !== n) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n `ephemeralSecrets.length=${args.ephemeralSecrets.length} must match recipientPublicKeys.length=${n}`,\n );\n }\n } else {\n if (args.ephemeralSecrets !== undefined) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n \"ephemeralSecrets is an X25519 override and MUST NOT be supplied for kem='mlkem768x25519'\",\n );\n }\n if (args.eseeds !== undefined) {\n if (args.eseeds.length !== n) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n `eseeds.length=${args.eseeds.length} must match recipientPublicKeys.length=${n}`,\n );\n }\n for (let i = 0; i < n; i++) {\n const eseed = args.eseeds[i]!;\n if (eseed.length !== MLKEM768X25519_ESEED_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_EPHEMERAL_SECRET_LENGTH',\n `eseeds[${i}] MUST be exactly ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${eseed.length}`,\n );\n }\n }\n }\n }\n\n const cek = args.cek ?? randomBytes(CEK_LENGTH);\n const nonce = args.nonce ?? randomBytes(NONCE_LENGTH);\n if (cek.length !== CEK_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_CEK_LENGTH',\n `cek MUST be exactly ${CEK_LENGTH} bytes, got ${cek.length}`,\n );\n }\n if (nonce.length !== NONCE_LENGTH) {\n throw new EciesSealedPoeError(\n 'NONCE_LENGTH_MISMATCH',\n `nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${nonce.length}`,\n );\n }\n\n let envelope: SealedEnvelope;\n // `slots_hash` is the SHA-256 of the header-bound slots transcript. It is\n // computed once here, fed into both the slot-set MAC and the content AAD.\n let slotsHash: Uint8Array;\n if (kem === 'x25519') {\n const slots: X25519Slot[] = [];\n for (let i = 0; i < n; i++) {\n slots.push(\n wrapSlotX25519({\n pubR: recipientPublicKeys[i]!,\n privEph: args.ephemeralSecrets ? (args.ephemeralSecrets[i] as Uint8Array) : undefined,\n cek,\n slotIdx: i,\n }),\n );\n }\n // Anonymity invariant (see csprngShuffle comment). The transcript is built\n // AFTER the shuffle so the MAC binds the on-wire slot order.\n if (args.skipShuffle !== true) {\n csprngShuffle(slots);\n }\n slotsHash = computeSlotsHash({ kem: 'x25519', nonce, slots });\n envelope = {\n scheme: 1,\n aead: 'xchacha20-poly1305',\n kem: 'x25519',\n nonce,\n slots,\n slots_mac: computeSlotsMac(cek, slotsHash),\n };\n } else {\n const slots: Mlkem768X25519Slot[] = [];\n for (let i = 0; i < n; i++) {\n slots.push(\n wrapSlotMlkem768X25519({\n pubR: recipientPublicKeys[i]!,\n eseed: args.eseeds ? (args.eseeds[i] as Uint8Array) : undefined,\n cek,\n }),\n );\n }\n if (args.skipShuffle !== true) {\n csprngShuffle(slots);\n }\n slotsHash = computeSlotsHash({ kem: 'mlkem768x25519', nonce, slots });\n envelope = {\n scheme: 1,\n aead: 'xchacha20-poly1305',\n kem: 'mlkem768x25519',\n nonce,\n slots,\n slots_mac: computeSlotsMac(cek, slotsHash),\n };\n }\n\n // Content is encrypted under a derived `payload_key` (a separate HKDF leaf of\n // the CEK keyed on the nonce), never under the CEK directly, so the wrap layer\n // and the content layer never key the same primitive on the same bytes. The\n // AAD re-binds the slots-path header and carries both `slots_hash` and\n // `slots_mac`.\n const payloadKey = slotsPayloadKey({ cek, nonce });\n const adContent = adContentSlots({\n kem: envelope.kem,\n nonce,\n slotsHash,\n slotsMac: envelope.slots_mac,\n });\n const ciphertext = xchacha20Poly1305Encrypt({\n key: payloadKey,\n nonce,\n aad: adContent,\n plaintext,\n });\n\n return { envelope, ciphertext };\n}\n\n// Slot-set MAC binds the slots transcript to the CEK. The transcript is pre-\n// hashed to a 32-byte `slots_hash` (header fields + canonicalised slot set,\n// including the entire chunked kem_ct on the hybrid path), and that hash is the\n// message of a CEK-keyed HMAC. Pre-hashing only changes the HMAC message from\n// the full transcript to its SHA-256, leaving the CEK-keyed commitment intact.\nfunction computeSlotsMac(cek: Uint8Array, slotsHash: Uint8Array): Uint8Array {\n const hmacKey = hkdfSha256({\n ikm: cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n length: 32,\n });\n const slotsMac = hmac(sha256, hmacKey, slotsHash);\n if (slotsMac.length !== SLOTS_MAC_LENGTH) {\n throw new Error(`internal: slots_mac.length=${slotsMac.length}, expected ${SLOTS_MAC_LENGTH}`);\n }\n return slotsMac;\n}\n","// Isomorphic constant-time byte-equality. crypto-core is browser-safe by\n// design, so we cannot import `node:crypto.timingSafeEqual` — webpack rejects\n// the `node:` scheme in the browser bundle. A pure-JS XOR loop is constant-time\n// for equal-length inputs; length mismatch is a deliberate early-return (the\n// API surface itself leaks length, same as node's timingSafeEqual which throws).\nexport function compareCt(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n // Lengths are equal and `i` stays in-bounds, so both indexes are always\n // defined — no nullish guard is needed (and one would read as a guard for\n // an impossible case).\n for (let i = 0; i < a.length; i++) diff |= (a[i] as number) ^ (b[i] as number);\n return diff === 0;\n}\n","// Multi-recipient sealed-PoE unwrap (age-style trial-decrypt\n// + constant-time slots_mac binding + partitioning-oracle length pre-checks).\n//\n// Two forms (mutually exclusive — exactly one MUST be supplied):\n//\n// • Single-priv form: `recipientSecretKey: Uint8Array` — the standalone-verifier\n// path. Runs the trial-decrypt loop over `envelope.slots` once.\n//\n// • Multi-priv form: `recipientSecretKeys: ReadonlyArray<Uint8Array>` — for the\n// trial-decrypt scan of a rotated identity holding `[currentPriv, ...archivedPrivs]`.\n// Caller supplies the order; the iterator runs outer-loop = privkey ×\n// inner-loop = slot, short-circuiting on the first cross-priv match that\n// passes slots_mac verification. The recommended caller order\n// is `[currentPriv, ...previousPrivsReversed]` (newest archive first).\n//\n// Constant-time-N (default `true`) applies PER PRIV (the inner loop): all slots\n// are entered regardless of match position. The outer loop short-circuits on\n// first cross-priv match — the cross-priv channel is intrinsic to trial-decrypt\n//\n// Both KEM branches share this control flow. The per-slot recovery body differs:\n// • x25519: X25519 ECDH → HKDF → AEAD-unwrap; may throw on a low-order\n// epk (RFC 7748 §6.1 contributory-check rejection), handled\n// as a non-match.\n// • mlkem768x25519: X-Wing decapsulate → HKDF → AEAD-unwrap; NEVER throws on\n// attacker wire data (ML-KEM implicit rejection yields a\n// pseudorandom shared secret), so no try/catch around it.\n\nimport { hmac } from '@noble/hashes/hmac.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nimport { chacha20Poly1305Decrypt } from '../aead/chacha20-poly1305';\nimport { AeadVerificationError } from '../aead/errors';\nimport { xchacha20Poly1305Decrypt } from '../aead/xchacha20-poly1305';\nimport { hkdfSha256 } from '../kdf/hkdf';\nimport {\n mlkem768x25519Decapsulate,\n mlkem768x25519Keygen,\n MLKEM768X25519_ENC_LENGTH,\n} from '../kem/mlkem768x25519';\nimport { x25519Ecdh, X25519LowOrderPointError, x25519PublicKey } from '../kem/x25519';\nimport { compareCt } from '../util/compare-ct';\n\nimport { EciesSealedPoeError } from './errors';\nimport { joinKemCt } from './slots-codec';\nimport {\n adContentSlots,\n assertCiphertextWithinBound,\n computeSlotsHash,\n MAX_DECODED_ENVELOPE_BYTES,\n MAX_SLOTS,\n slotsPayloadKey,\n xwingKekSalt,\n} from './transcript';\nimport {\n CARDANO_POE_HKDF_INFO_KEK,\n CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n type Mlkem768X25519Slot,\n type SealedEnvelope,\n type X25519Slot,\n} from './wrap';\n\nexport type UnwrapFailureReason = 'WRONG_RECIPIENT_KEY' | 'TAMPERED_HEADER' | 'TAMPERED_CIPHERTEXT';\n\nexport type UnwrapResult =\n | { readonly matched: true; readonly plaintext: Uint8Array }\n | { readonly matched: false; readonly reason: UnwrapFailureReason };\n\n// Unified recipient key bundle. Callers hold BOTH the X25519\n// private-key chain (current + archived, for classical and rotation history)\n// AND the X-Wing secret seed(s) (for the hybrid KEM), without knowing which a\n// given record was sealed under. They pass the whole bundle; the unwrap /\n// trial-decrypt dispatch selects the correct secret list from `envelope.kem`:\n//\n// • kem === 'x25519' → bundle.x25519PrivateKeys\n// • kem === 'mlkem768x25519' → bundle.mlkem768x25519SecretSeeds\n//\n// Both lists are ordered newest-first (caller's responsibility — the outer\n// trial-decrypt loop scans them in order). A list MAY be empty when the\n// recipient holds no key for that KEM (e.g. archived-only X25519 identities\n// predate the hybrid KEM, so their hybrid seed list is empty); a bundle whose\n// selected list is empty unwraps to a clean WRONG_RECIPIENT_KEY / no_aead_pass\n// without touching any KEM primitive.\nexport interface RecipientKeyBundle {\n readonly x25519PrivateKeys: ReadonlyArray<Uint8Array>;\n readonly mlkem768x25519SecretSeeds: ReadonlyArray<Uint8Array>;\n}\n\n// Select the secret-key list a bundle contributes for the given envelope KEM.\n// The single dispatch seam — wrap and trial-decrypt both route through here so\n// the per-KEM selection lives in exactly one place.\nfunction selectBundleSecrets(\n envelope: SealedEnvelope,\n bundle: RecipientKeyBundle,\n): ReadonlyArray<Uint8Array> {\n return envelope.kem === 'x25519' ? bundle.x25519PrivateKeys : bundle.mlkem768x25519SecretSeeds;\n}\n\ninterface UnwrapArgsCommon {\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n readonly constantTimeN?: boolean;\n // Test-only instrumentation for constant-time-N verification.\n // The unwrap fn bumps `count` once per inner-loop iteration entered. In the\n // multi-priv path, `count` is reset at the start of each outer iteration and\n // — when `perPrivCounts` is provided — the final per-priv inner count is\n // appended after that priv's inner loop completes. Production callers never\n // pass this.\n readonly _slotsAttemptedOut?: { count: number; perPrivCounts?: number[] };\n // Test-only multi-priv outer-loop iteration counter. Bumped to `k + 1` at\n // the start of each outer-loop iteration. Production callers never pass this.\n readonly _privsAttemptedOut?: { count: number };\n}\n\nexport interface UnwrapArgsSinglePriv extends UnwrapArgsCommon {\n readonly recipientSecretKey: Uint8Array;\n}\n\nexport interface UnwrapArgsMultiPriv extends UnwrapArgsCommon {\n readonly recipientSecretKeys: ReadonlyArray<Uint8Array>;\n}\n\n// Bundle form of the multi-priv path: the caller passes both KEMs' secret\n// lists and the dispatch picks the right one from `envelope.kem`. This is the\n// surface every read-path consumer (inbox decrypt, CLI decrypt, standalone\n// recipient verifier) should use — they hold the whole identity key bundle and\n// must NOT pre-select a list or rebuild slots themselves.\nexport interface UnwrapArgsBundle extends UnwrapArgsCommon {\n readonly recipientKeyBundle: RecipientKeyBundle;\n}\n\nexport type UnwrapArgs = UnwrapArgsSinglePriv | UnwrapArgsMultiPriv | UnwrapArgsBundle;\n\n// Trial-decrypt-only sibling of eciesSealedPoeUnwrap. Runs the\n// per-slot AEAD + slots_mac check but NEVER calls the content AEAD (which\n// requires the off-chain `ciphertext` blob, not available at trial-decrypt\n// time). Used by an inbox-scan agent to discover readable records before\n// fetching their ciphertext.\ninterface TrialDecryptOnlyArgsCommon {\n readonly envelope: SealedEnvelope;\n readonly constantTimeN?: boolean;\n readonly _slotsAttemptedOut?: { count: number; perPrivCounts?: number[] };\n readonly _privsAttemptedOut?: { count: number };\n}\n\n// Exactly one of `recipientSecretKeys` (flat, KEM-pre-selected) or\n// `recipientKeyBundle` (whole bundle, KEM dispatched from `envelope.kem`).\n// Inbox-scan consumers pass the bundle; the low-level / parity tests pass the\n// flat list directly.\nexport type TrialDecryptOnlyArgs = TrialDecryptOnlyArgsCommon &\n (\n | { readonly recipientSecretKeys: ReadonlyArray<Uint8Array> }\n | { readonly recipientKeyBundle: RecipientKeyBundle }\n );\n\nexport type TrialDecryptOnlyResult =\n | { readonly kind: 'match'; readonly slotIdx: number; readonly cek: Uint8Array }\n | { readonly kind: 'no_aead_pass' }\n | { readonly kind: 'aead_pass_no_mac_match' };\n\nconst ZERO_NONCE_12: Uint8Array = new Uint8Array(12);\nconst EMPTY_SALT: Uint8Array = new Uint8Array(0);\nconst X25519_SECRET_KEY_LENGTH = 32 as const;\nconst X25519_PUBLIC_KEY_LENGTH = 32 as const;\nconst NONCE_LENGTH = 24 as const;\nconst WRAP_LENGTH = 48 as const;\nconst SLOTS_MAC_LENGTH = 32 as const;\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n// Stable string key for a byte string, used only for the per-slot KEM-material\n// duplicate check (a structural pre-trial gate, not a constant-time comparison).\nfunction bytesKey(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) {\n s += String.fromCharCode(bytes[i]!);\n }\n return s;\n}\n\n// Partitioning-oracle defence: every wire\n// length MUST be validated before any KEM/AEAD primitive is invoked, so malformed\n// records cannot probe per-slot failure ordering. Shared between\n// `eciesSealedPoeUnwrap` (single- and multi-priv) and `eciesSealedPoeTrialDecrypt`\n// to guarantee byte-identical pre-trial behaviour and to keep the dispatch\n// invariant in one place. For the hybrid branch this includes reassembling each\n// slot's `kem_ct` and asserting the flat enc length BEFORE any decapsulation.\nfunction assertEnvelopeStructure(\n envelope: SealedEnvelope,\n multiPrivKeys?: ReadonlyArray<Uint8Array>,\n singlePrivKey?: Uint8Array,\n): void {\n if (envelope.scheme !== 1) {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_ENC_VERSION',\n `envelope.scheme=${String(envelope.scheme)} unsupported (expected 1)`,\n );\n }\n if (envelope.aead !== 'xchacha20-poly1305') {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_AEAD_ALG',\n `envelope.aead=${String(envelope.aead)} unsupported (expected 'xchacha20-poly1305')`,\n );\n }\n if (envelope.kem !== 'x25519' && envelope.kem !== 'mlkem768x25519') {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_KEM_ALG',\n `envelope.kem=${String((envelope as { kem: string }).kem)} unsupported (expected 'x25519' or 'mlkem768x25519')`,\n );\n }\n\n // Envelope-level length pre-checks in this exact order.\n const n = envelope.slots.length;\n if (n < 1) {\n throw new EciesSealedPoeError('ENC_SLOTS_EMPTY', `envelope.slots.length=${n} must be >= 1`);\n }\n // Resource bound: reject an envelope with more than MAX_SLOTS slots before any\n // KEM/AEAD primitive runs, so a malformed record cannot drive unbounded\n // per-slot work. Checked before the per-slot length loop below.\n if (n > MAX_SLOTS) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_TOO_MANY',\n `envelope.slots.length=${n} exceeds MAX_SLOTS=${MAX_SLOTS}`,\n );\n }\n if (envelope.nonce.length !== NONCE_LENGTH) {\n throw new EciesSealedPoeError(\n 'NONCE_LENGTH_MISMATCH',\n `envelope.nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${envelope.nonce.length}`,\n );\n }\n if (envelope.slots_mac.length !== SLOTS_MAC_LENGTH) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_MAC_INVALID_LENGTH',\n `envelope.slots_mac MUST be exactly ${SLOTS_MAC_LENGTH} bytes, got ${envelope.slots_mac.length}`,\n );\n }\n\n // Per-slot length pre-checks — KEM-driven. ALL slots are validated here,\n // before any decapsulation, so the trial-decrypt loop never observes a\n // malformed slot (partitioning-oracle-safe ordering).\n //\n // Per-slot KEK uniqueness is also enforced here. The zero-nonce per-slot wrap\n // is safe only because each slot draws fresh KEM randomness, so its KEK is\n // unique; two slots sharing the same KEM material derive the same KEK and\n // repeat a (KEK, zero-nonce) pair. The KEM material that fixes the KEK is the\n // `epk` (x25519) or the reassembled `kem_ct` (hybrid) — both bound into the\n // KEK salt — so a repeat of either across slots is rejected outright.\n const seenKemMaterial = new Set<string>();\n if (envelope.kem === 'x25519') {\n for (let i = 0; i < n; i++) {\n const slot = envelope.slots[i]!;\n if (slot.epk.length !== X25519_PUBLIC_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'KEM_EPK_LENGTH_MISMATCH',\n `envelope.slots[${i}].epk MUST be exactly ${X25519_PUBLIC_KEY_LENGTH} bytes, got ${slot.epk.length}`,\n );\n }\n if (slot.wrap.length !== WRAP_LENGTH) {\n throw new EciesSealedPoeError(\n 'WRAP_LENGTH_MISMATCH',\n `envelope.slots[${i}].wrap MUST be exactly ${WRAP_LENGTH} bytes, got ${slot.wrap.length}`,\n );\n }\n const key = bytesKey(slot.epk);\n if (seenKemMaterial.has(key)) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL',\n `envelope.slots[${i}].epk duplicates an earlier slot — per-slot KEK uniqueness is violated`,\n );\n }\n seenKemMaterial.add(key);\n }\n } else {\n for (let i = 0; i < n; i++) {\n const slot = envelope.slots[i]!;\n const enc = joinKemCt(slot.kem_ct);\n if (enc.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new EciesSealedPoeError(\n 'KEM_CT_LENGTH_MISMATCH',\n `envelope.slots[${i}].kem_ct MUST reassemble to exactly ${MLKEM768X25519_ENC_LENGTH} bytes, got ${enc.length}`,\n );\n }\n if (slot.wrap.length !== WRAP_LENGTH) {\n throw new EciesSealedPoeError(\n 'WRAP_LENGTH_MISMATCH',\n `envelope.slots[${i}].wrap MUST be exactly ${WRAP_LENGTH} bytes, got ${slot.wrap.length}`,\n );\n }\n const key = bytesKey(enc);\n if (seenKemMaterial.has(key)) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL',\n `envelope.slots[${i}].kem_ct duplicates an earlier slot — per-slot KEK uniqueness is violated`,\n );\n }\n seenKemMaterial.add(key);\n }\n }\n\n // Decoded-envelope byte backstop. Every per-slot field above is validated to a\n // fixed length, so the decoded envelope's aggregate size is determined here:\n // nonce + slots_mac + per-slot (epk|kem_ct + wrap). Reject before any KEM/AEAD\n // primitive when it exceeds the bound — a tighter resource cap than MAX_SLOTS\n // for honest records, and the bound a parser that can see the decoded size\n // enforces. (The slot-count cap above already bounds work; this is the byte\n // backstop the spec also pins.)\n const perSlotBytes =\n envelope.kem === 'x25519'\n ? X25519_PUBLIC_KEY_LENGTH + WRAP_LENGTH\n : MLKEM768X25519_ENC_LENGTH + WRAP_LENGTH;\n const decodedEnvelopeBytes = NONCE_LENGTH + SLOTS_MAC_LENGTH + n * perSlotBytes;\n if (decodedEnvelopeBytes > MAX_DECODED_ENVELOPE_BYTES) {\n throw new EciesSealedPoeError(\n 'ENC_ENVELOPE_TOO_LARGE',\n `decoded envelope size ${decodedEnvelopeBytes} exceeds MAX_DECODED_ENVELOPE_BYTES=${MAX_DECODED_ENVELOPE_BYTES}`,\n );\n }\n\n if (multiPrivKeys !== undefined) {\n for (let i = 0; i < multiPrivKeys.length; i++) {\n if (multiPrivKeys[i]!.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n `recipientSecretKeys[${i}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${multiPrivKeys[i]!.length}`,\n );\n }\n }\n } else if (singlePrivKey !== undefined) {\n if (singlePrivKey.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n `recipientSecretKey MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${singlePrivKey.length}`,\n );\n }\n }\n}\n\n// All-zero IKM for the dummy KEK an invalid-ECDH slot derives so it pays the\n// same HKDF work as a live slot (see `tryX25519Slot`).\nconst ZERO_IKM_32: Uint8Array = new Uint8Array(32);\n\n// Classical (x25519) per-slot recovery body. Returns the candidate CEK on an\n// AEAD-tag success; null otherwise. The AEAD is attempted on EVERY slot (no\n// match-position-dependent skip), so a per-priv scan recovers a candidate CEK\n// from each slot the recipient is addressed in — which is what the inner loop's\n// CEK-conflict detection needs. Attempting the AEAD on every slot also makes the\n// per-slot timing more uniform, not less: every slot pays the identical\n// ECDH + HKDF + AEAD-open cost regardless of where the match lands.\n//\n// Acceptance is `kem_ok AND open_ok`. `kem_ok` is the X25519 validity bit: a\n// small-order `epk` drives the shared secret to all-zero, which RFC 7748 §6.1\n// rejects. @noble/curves signals this by THROWING from `getSharedSecret`, so a\n// fully branchless ct-select over the shared secret is not expressible against\n// this library API. The next-best, equivalent form is taken instead: on the\n// all-zero rejection the slot derives a DUMMY KEK from `ikm=0^32` (same\n// salt/info) so it performs the identical HKDF work, then returns a non-match\n// WITHOUT attempting the AEAD — so an invalid-ECDH slot can never be accepted\n// regardless of the wrap outcome (`kem_ok=false` ⟹ the AEAD is never reached),\n// while the failed path still costs the same per-slot KEK derivation as a live\n// one.\nfunction tryX25519Slot(args: {\n slot: X25519Slot;\n recipientSecretKey: Uint8Array;\n pubRLocal: Uint8Array;\n}): Uint8Array | null {\n const salt = concat(args.slot.epk, args.pubRLocal);\n let shared: Uint8Array;\n try {\n shared = x25519Ecdh({\n secretKey: args.recipientSecretKey,\n theirPublicKey: args.slot.epk,\n });\n } catch (e) {\n if (!(e instanceof X25519LowOrderPointError)) throw e;\n // kem_ok = false. Derive the dummy KEK so the failed slot pays the same\n // HKDF cost a live slot would, then short-circuit to a non-match: the AEAD\n // is never attempted, so this slot can never be accepted.\n hkdfSha256({ ikm: ZERO_IKM_32, salt, info: CARDANO_POE_HKDF_INFO_KEK, length: 32 });\n return null;\n }\n // kem_ok = true. Derive the real KEK and attempt the wrap AEAD.\n const kek = hkdfSha256({ ikm: shared, salt, info: CARDANO_POE_HKDF_INFO_KEK, length: 32 });\n try {\n return chacha20Poly1305Decrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK,\n ciphertext: args.slot.wrap,\n });\n } catch (e) {\n if (!(e instanceof AeadVerificationError)) throw e;\n return null;\n }\n}\n\n// Hybrid (mlkem768x25519) per-slot recovery body. X-Wing decapsulate NEVER\n// throws on attacker wire data (ML-KEM implicit rejection), so there is no\n// try/catch: a wrong shared secret simply yields a KEK that fails the AEAD tag.\n// As in the classical body, the AEAD is attempted on EVERY slot (full\n// decapsulate + HKDF + AEAD-open) so matching and non-matching slots cost the\n// same X-Wing work and a per-priv scan recovers a candidate CEK from every slot\n// the recipient is addressed in.\nfunction tryMlkem768X25519Slot(args: {\n slot: Mlkem768X25519Slot;\n recipientSecretKey: Uint8Array;\n pubR: Uint8Array;\n}): Uint8Array | null {\n // kem_ct length was validated to reassemble to MLKEM768X25519_ENC_LENGTH in\n // assertEnvelopeStructure, so this join + decapsulate is constant-work.\n const enc = joinKemCt(args.slot.kem_ct);\n const ss = mlkem768x25519Decapsulate({ secretSeed: args.recipientSecretKey, enc });\n // The KEK salt binds the slot's own reassembled ciphertext and the recipient's\n // own X-Wing public key (recomputed from the held seed), exactly as the\n // producer bound them — see the wrap path.\n const kek = hkdfSha256({\n ikm: ss,\n salt: xwingKekSalt({ kemCt: enc, pubR: args.pubR }),\n info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n length: 32,\n });\n try {\n return chacha20Poly1305Decrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n ciphertext: args.slot.wrap,\n });\n } catch (e) {\n if (!(e instanceof AeadVerificationError)) throw e;\n return null;\n }\n}\n\n// The recovered CEK plus a defence-in-depth conflict flag. A producer may\n// legitimately address the same recipient (or wrap the same CEK) in several\n// slots, so multiple matching slots are PERMITTED and the first match's CEK is\n// selected. But two matching slots that recover DIFFERENT CEKs (both satisfying\n// their per-slot wrap AEAD) is a commitment collision the §G4 assumption rules\n// out; `cekConflict` flags it so the caller can fail closed. The compare is\n// constant-time; the inner loop visits every slot (constant-time-N), so the\n// flag does not leak match position.\ninterface InnerUnwrapResult {\n readonly cek: Uint8Array;\n readonly slotIdx: number;\n readonly cekConflict: boolean;\n}\n\n// Per-priv inner trial-decrypt loop with slot-index reporting and CEK-conflict\n// detection, KEM-driven. Enters every slot when constantTimeN; every slot\n// attempts the wrap AEAD, so a recipient addressed in multiple slots recovers a\n// candidate CEK from each. The first match's CEK is selected; any later match\n// recovering a CEK that differs (constant-time compare) from the selected one\n// sets `cekConflict`. This follows the spec loop shape:\n//\n// first = ok AND NOT found\n// cek_conflict = cek_conflict OR (ok AND found AND NOT ctEq(cand, selected))\n// selected_CEK = first ? cand : selected\n// found = found OR ok\n//\n// No early break is taken when constantTimeN, so the conflict scan is constant\n// across the whole slot set.\nfunction tryRecipientUnwrapWithIdx(\n envelope: SealedEnvelope,\n recipientSecretKey: Uint8Array,\n constantTimeN: boolean,\n slotsAttemptedOut: { count: number; perPrivCounts?: number[] } | undefined,\n): InnerUnwrapResult | null {\n const n = envelope.slots.length;\n let cek: Uint8Array | null = null;\n let matchedSlotIdx = -1;\n let cekConflict = false;\n\n const recordMatch = (candidate: Uint8Array | null, i: number): void => {\n if (candidate === null) return;\n if (cek === null) {\n // first = ok AND NOT found.\n cek = candidate;\n matchedSlotIdx = i;\n } else if (!compareCt(candidate, cek)) {\n // ok AND found AND NOT ctEq(cand, selected) — a later matching slot whose\n // recovered CEK differs from the already-selected one. Fail closed.\n cekConflict = true;\n }\n };\n\n if (envelope.kem === 'x25519') {\n const pubRLocal = x25519PublicKey({ secretKey: recipientSecretKey });\n for (let i = 0; i < n; i++) {\n if (slotsAttemptedOut !== undefined) {\n slotsAttemptedOut.count = i + 1;\n }\n recordMatch(tryX25519Slot({ slot: envelope.slots[i]!, recipientSecretKey, pubRLocal }), i);\n if (cek !== null && !constantTimeN) break;\n }\n } else {\n // Recompute the recipient's own X-Wing public key from the held seed: the\n // hybrid KEK salt binds `pub_R`, so each private key in a multi-key scan\n // MUST re-derive it (a single shared pub_R would compute the wrong KEK for\n // every key but one).\n const pubR = mlkem768x25519Keygen(recipientSecretKey).publicKey;\n for (let i = 0; i < n; i++) {\n if (slotsAttemptedOut !== undefined) {\n slotsAttemptedOut.count = i + 1;\n }\n recordMatch(tryMlkem768X25519Slot({ slot: envelope.slots[i]!, recipientSecretKey, pubR }), i);\n if (cek !== null && !constantTimeN) break;\n }\n }\n return cek === null ? null : { cek, slotIdx: matchedSlotIdx, cekConflict };\n}\n\n// 32-byte slots-transcript hash. The transcript binds the cross-KEM header\n// fields (scheme, path, aead, kem, nonce) to the canonicalised slot set, so the\n// hybrid kem_ct is committed by its bytes (chunk-boundary-invariant). It depends\n// only on the header and the slots, so it is constant across the multi-priv\n// outer loop and the per-slot trial-decrypt loop — callers compute it ONCE and\n// re-key the HMAC from each candidate CEK over this same 32-byte message.\nfunction slotsHashBytes(envelope: SealedEnvelope): Uint8Array {\n return computeSlotsHash({\n kem: envelope.kem,\n nonce: envelope.nonce,\n slots: envelope.slots as ReadonlyArray<X25519Slot | Mlkem768X25519Slot>,\n });\n}\n\nexport function eciesSealedPoeUnwrap(args: UnwrapArgs): UnwrapResult {\n const { envelope, ciphertext } = args;\n const constantTimeN = args.constantTimeN ?? true;\n\n // Exactly-one-of validation across the three UnwrapArgs forms (single-priv,\n // flat multi-priv, bundle). Runs before any AEAD / wire-shape work so a\n // malformed call cannot probe per-slot AEAD timing. The bundle form resolves\n // to a flat multi-priv list here by dispatching on `envelope.kem` — from this\n // point the loop is identical regardless of how the caller supplied keys.\n const hasSingle = 'recipientSecretKey' in args;\n const hasBundle = 'recipientKeyBundle' in args;\n const multiPrivKeys: ReadonlyArray<Uint8Array> | undefined = hasBundle\n ? selectBundleSecrets(envelope, (args as UnwrapArgsBundle).recipientKeyBundle)\n : 'recipientSecretKeys' in args\n ? (args as UnwrapArgsMultiPriv).recipientSecretKeys\n : undefined;\n const hasMulti = multiPrivKeys !== undefined;\n if (hasSingle === hasMulti) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'exactly one of recipientSecretKey / recipientSecretKeys / recipientKeyBundle MUST be supplied',\n );\n }\n // A bundle selecting an empty list for this KEM means the recipient holds no\n // key of the matching kind (e.g. an archived-only identity facing a hybrid\n // record). That is a legitimate non-match, NOT a malformed call — return a\n // clean WRONG_RECIPIENT_KEY without invoking any KEM primitive. The flat\n // multi-priv form keeps the original \"empty array is a programmer error\"\n // contract its callers (and step-3 tests) rely on.\n if (hasMulti && multiPrivKeys!.length === 0) {\n if (hasBundle) {\n return { matched: false, reason: 'WRONG_RECIPIENT_KEY' };\n }\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'recipientSecretKeys MUST be a non-empty array, got length=0',\n );\n }\n\n // Partitioning-oracle pre-checks; per-priv length validation happens\n // inside `assertEnvelopeStructure`.\n if (hasMulti) {\n assertEnvelopeStructure(envelope, multiPrivKeys, undefined);\n } else {\n assertEnvelopeStructure(envelope, undefined, (args as UnwrapArgsSinglePriv).recipientSecretKey);\n }\n\n // Reject a ciphertext at or above the single-shot keystream capacity before\n // any KEM/AEAD work, so an over-large blob never reaches the content open.\n assertCiphertextWithinBound(ciphertext.length);\n\n // Trial-decrypt loop. With constantTimeN=true the loop\n // entries are uniform regardless of match position; the per-iteration body\n // does the same KEM + HKDF work in both branches.\n\n // The slots-transcript hash is constant across both the single-priv MAC check\n // and the multi-priv outer loop — compute it ONCE, then re-key the HMAC from\n // each candidate CEK over this same 32-byte message.\n const slotsHash = slotsHashBytes(envelope);\n\n let matchedCek: Uint8Array | null = null;\n let anyCandidateRecovered = false;\n\n if (hasSingle) {\n const recipientSecretKey = (args as UnwrapArgsSinglePriv).recipientSecretKey;\n const candidate = tryRecipientUnwrapWithIdx(\n envelope,\n recipientSecretKey,\n constantTimeN,\n args._slotsAttemptedOut,\n );\n if (candidate === null) {\n return { matched: false, reason: 'WRONG_RECIPIENT_KEY' };\n }\n // CEK-conflict defence-in-depth: a later matching slot recovered a CEK that\n // differs from the selected one. Fail closed with the generic tampered-header\n // reason (a commitment collision is a broken/anomalous slot set, not a\n // recipient-key mismatch).\n if (candidate.cekConflict) {\n return { matched: false, reason: 'TAMPERED_HEADER' };\n }\n // Slot-set MAC verification. Use compareCt to\n // avoid leaking byte-position via early-exit on first mismatching byte.\n const hmacKey = hkdfSha256({\n ikm: candidate.cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n length: 32,\n });\n const slotsMacCalc = hmac(sha256, hmacKey, slotsHash);\n if (!compareCt(slotsMacCalc, envelope.slots_mac)) {\n return { matched: false, reason: 'TAMPERED_HEADER' };\n }\n matchedCek = candidate.cek;\n } else {\n const recipientSecretKeys = multiPrivKeys!;\n let cekConflict = false;\n for (let k = 0; k < recipientSecretKeys.length; k++) {\n if (args._privsAttemptedOut !== undefined) {\n args._privsAttemptedOut.count = k + 1;\n }\n if (args._slotsAttemptedOut !== undefined) {\n args._slotsAttemptedOut.count = 0;\n }\n const candidate = tryRecipientUnwrapWithIdx(\n envelope,\n recipientSecretKeys[k]!,\n constantTimeN,\n args._slotsAttemptedOut,\n );\n if (args._slotsAttemptedOut?.perPrivCounts !== undefined) {\n args._slotsAttemptedOut.perPrivCounts.push(args._slotsAttemptedOut.count);\n }\n if (candidate === null) continue;\n // A per-priv CEK conflict (two of this priv's slots recovering different\n // CEKs) makes the whole record anomalous regardless of which priv matched\n // the MAC — record it and fail closed after the loop.\n if (candidate.cekConflict) cekConflict = true;\n const cek = candidate.cek;\n // Slot-set MAC verification per priv that recovered a candidate CEK.\n const hmacKey = hkdfSha256({\n ikm: cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n length: 32,\n });\n const slotsMacCalc = hmac(sha256, hmacKey, slotsHash);\n // The outer cross-priv loop short-circuits on the first priv whose\n // recovered CEK also passes slots_mac. This intentionally leaks \"which\n // priv matched\" → \"how many key rotations the recipient has performed\".\n // We accept it: trial-decrypt runs client-side, so this timing is only\n // locally observable, and the leak is a weak ordering signal, not a\n // key/plaintext oracle. Making the outer loop constant-work would cost a\n // FULL KEM decapsulation (an X25519 ECDH, or — for the hybrid branch — a\n // full X-Wing ML-KEM-768 + X25519 decapsulation) for EVERY archived priv\n // on EVERY record, which for the hybrid case is the dominant cost; the\n // benefit (hiding a count the user already knows) does not justify it.\n // The inner per-slot loop IS held constant-work (constant-time-N).\n if (compareCt(slotsMacCalc, envelope.slots_mac)) {\n matchedCek = cek;\n break;\n }\n anyCandidateRecovered = true;\n }\n // A CEK conflict on the matching priv fails the record closed, even if its\n // first-slot CEK passed slots_mac.\n if (matchedCek !== null && cekConflict) {\n return { matched: false, reason: 'TAMPERED_HEADER' };\n }\n if (matchedCek === null) {\n return {\n matched: false,\n reason: anyCandidateRecovered ? 'TAMPERED_HEADER' : 'WRONG_RECIPIENT_KEY',\n };\n }\n }\n\n // Content is opened under the derived `payload_key`, with the structured\n // slots-path AAD re-binding the header plus `slots_hash` and `slots_mac`.\n const payloadKey = slotsPayloadKey({ cek: matchedCek, nonce: envelope.nonce });\n const adContent = adContentSlots({\n kem: envelope.kem,\n nonce: envelope.nonce,\n slotsHash,\n slotsMac: envelope.slots_mac,\n });\n try {\n const plaintext = xchacha20Poly1305Decrypt({\n key: payloadKey,\n nonce: envelope.nonce,\n aad: adContent,\n ciphertext,\n });\n return { matched: true, plaintext };\n } catch (e) {\n if (!(e instanceof AeadVerificationError)) throw e;\n return { matched: false, reason: 'TAMPERED_CIPHERTEXT' };\n }\n}\n\n// Trial-decrypt half of the sealed-PoE unwrap algorithm:\n// recovers the CEK + slot index without touching the content AEAD. Used by an\n// inbox-scan agent where the on-chain `metadata_cbor` envelope is available but\n// the off-chain ciphertext blob is fetched lazily only when the user invokes\n// Decrypt.\n//\n// Mirrors the multi-priv branch of `eciesSealedPoeUnwrap`: same\n// partitioning-oracle pre-checks, same per-priv inner loop, same\n// constant-time-N invariant (default `true` — MANDATORY for untrusted scan\n// agents), same `compareCt` slots_mac check. Differs only\n// in the return shape: `{kind: 'match', slotIdx, cek}` instead of plaintext;\n// `{kind: 'aead_pass_no_mac_match'}`\n// instead of `TAMPERED_HEADER`; `{kind: 'no_aead_pass'}` instead of\n// `WRONG_RECIPIENT_KEY`. Cross-priv variable-time short-circuit is preserved\n// (leaks \"which priv matched\" → \"how many rotations\",\n// a documented weak ordering signal).\nexport function eciesSealedPoeTrialDecrypt(args: TrialDecryptOnlyArgs): TrialDecryptOnlyResult {\n const { envelope } = args;\n const constantTimeN = args.constantTimeN ?? true;\n\n // Bundle form selects the per-KEM list from `envelope.kem`; flat form is\n // already KEM-pre-selected. An empty bundle list for this KEM is a clean\n // no_aead_pass (the recipient holds no key of the matching kind), whereas an\n // empty flat list stays a programmer error (its callers / step-3 tests rely\n // on the throw).\n const hasBundle = 'recipientKeyBundle' in args;\n const recipientSecretKeys: ReadonlyArray<Uint8Array> = hasBundle\n ? selectBundleSecrets(envelope, args.recipientKeyBundle)\n : args.recipientSecretKeys;\n\n if (recipientSecretKeys.length === 0) {\n if (hasBundle) {\n return { kind: 'no_aead_pass' };\n }\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'recipientSecretKeys MUST be a non-empty array, got length=0',\n );\n }\n assertEnvelopeStructure(envelope, recipientSecretKeys, undefined);\n\n const slotsHash = slotsHashBytes(envelope);\n\n let anyCandidateRecovered = false;\n for (let k = 0; k < recipientSecretKeys.length; k++) {\n if (args._privsAttemptedOut !== undefined) {\n args._privsAttemptedOut.count = k + 1;\n }\n if (args._slotsAttemptedOut !== undefined) {\n args._slotsAttemptedOut.count = 0;\n }\n const candidate = tryRecipientUnwrapWithIdx(\n envelope,\n recipientSecretKeys[k]!,\n constantTimeN,\n args._slotsAttemptedOut,\n );\n if (args._slotsAttemptedOut?.perPrivCounts !== undefined) {\n args._slotsAttemptedOut.perPrivCounts.push(args._slotsAttemptedOut.count);\n }\n if (candidate === null) continue;\n // CEK-conflict defence-in-depth: this priv recovered different CEKs from two\n // matching slots — an anomalous slot set. Surface it as the generic\n // aead_pass_no_mac_match outcome (the trial-decrypt analogue of the unwrap\n // TAMPERED_HEADER rejection: a CEK opened but the slot set is not trusted),\n // never a clean match.\n if (candidate.cekConflict) {\n anyCandidateRecovered = true;\n continue;\n }\n const hmacKey = hkdfSha256({\n ikm: candidate.cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n length: 32,\n });\n const slotsMacCalc = hmac(sha256, hmacKey, slotsHash);\n if (compareCt(slotsMacCalc, envelope.slots_mac)) {\n return { kind: 'match', slotIdx: candidate.slotIdx, cek: candidate.cek };\n }\n anyCandidateRecovered = true;\n }\n return anyCandidateRecovered ? { kind: 'aead_pass_no_mac_match' } : { kind: 'no_aead_pass' };\n}\n","// Raw-seed identity surface. A developer holding a 32-byte seed (e.g. the\n// decoded hex of a key exported from another tool) can derive every keypair,\n// obtain their age recipient strings, get a path-1 Signer, build the\n// RecipientKeyBundle the unwrap dispatch consumes, and decrypt a sealed PoE —\n// all from the public SDK, without a web account envelope.\n//\n// The seed is the only secret this module touches. Callers are responsible for\n// sourcing it securely; the SDK never persists or logs it.\n\nimport {\n deriveEd25519KeypairFromSeed,\n deriveX25519KeypairFromSeed,\n deriveMlKem768X25519KeypairFromSeed,\n type DerivedEd25519KeyPair,\n type DerivedX25519KeyPair,\n type DerivedMlKem768X25519KeyPair,\n} from '@cardanowall/crypto-core/seed-derive';\nimport {\n encodeAgeX25519Recipient,\n encodeAgeXWingRecipient,\n} from '@cardanowall/crypto-core/recipient';\nimport {\n eciesSealedPoeUnwrap,\n type RecipientKeyBundle,\n type SealedEnvelope,\n type UnwrapResult,\n} from '@cardanowall/crypto-core/sealed-poe';\nimport { signEd25519 } from '@cardanowall/crypto-core/sig';\n\nimport type { Signer } from '../client/types';\n\nexport interface SeedKeys {\n readonly ed25519: DerivedEd25519KeyPair;\n readonly x25519: DerivedX25519KeyPair;\n readonly mlkem768x25519: DerivedMlKem768X25519KeyPair;\n}\n\n// Derive the three identity keypairs from a 32-byte seed: Ed25519 (record\n// signing), X25519 (classical KEM), and ML-KEM-768 + X25519 / X-Wing (hybrid\n// post-quantum KEM). Each keypair is the same byte-for-byte value the account\n// envelope would expose — the seed alone fully determines the identity.\nexport function deriveKeysFromSeed(seed: Uint8Array): SeedKeys {\n return {\n ed25519: deriveEd25519KeypairFromSeed(seed),\n x25519: deriveX25519KeypairFromSeed(seed),\n mlkem768x25519: deriveMlKem768X25519KeypairFromSeed(seed),\n };\n}\n\nexport interface SeedRecipients {\n /** Classical age recipient (\"age1…\") for the X25519 KEM. */\n readonly age: string;\n /** X-Wing hybrid recipient (\"age1pqc…\") for the ML-KEM-768 + X25519 KEM. */\n readonly age1pqc: string;\n}\n\n// The recipient strings other senders use to address this identity. Both\n// always exist for any seed: the X-Wing keypair derives for free, so every\n// identity can receive hybrid sealed records even when it publishes via the\n// classical X25519 path.\nexport function recipientsFromSeed(seed: Uint8Array): SeedRecipients {\n const keys = deriveKeysFromSeed(seed);\n return {\n age: encodeAgeX25519Recipient(keys.x25519.publicKey),\n age1pqc: encodeAgeXWingRecipient(keys.mlkem768x25519.publicKey),\n };\n}\n\n// An in-memory path-1 Signer for the publish helpers / off-host signing\n// surface. The derived Ed25519 secret lives only inside this closure; the\n// SDK's publish path touches just `signerPubkey` (public) and the 64-byte\n// signature (public). The 32-byte HKDF output IS the noble Ed25519 seed, so it\n// feeds `signEd25519` directly.\nexport function signerFromSeed(seed: Uint8Array): Signer {\n const { secretKey, publicKey } = deriveEd25519KeypairFromSeed(seed);\n return {\n signerPubkey: publicKey,\n async sign(sigStructureBytes: Uint8Array): Promise<Uint8Array> {\n return signEd25519({ seed: secretKey, message: sigStructureBytes });\n },\n };\n}\n\n// The unified RecipientKeyBundle for the trial-decrypt / unwrap dispatch. A\n// single active identity contributes a one-element X25519 private-key chain and\n// a one-element X-Wing secret-seed list; the unwrap dispatch selects the right\n// list from `envelope.kem`.\nexport function recipientKeyBundleFromSeed(seed: Uint8Array): RecipientKeyBundle {\n const keys = deriveKeysFromSeed(seed);\n return {\n x25519PrivateKeys: [keys.x25519.secretKey],\n mlkem768x25519SecretSeeds: [keys.mlkem768x25519.secretSeed],\n };\n}\n\nexport interface DecryptSealedFromSeedArgs {\n readonly seed: Uint8Array;\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n}\n\n// Decrypt a sealed PoE envelope + ciphertext from the seed. Builds the bundle\n// and routes through the existing unwrap dispatch, which selects the correct\n// secret list from `envelope.kem` — so the same call decrypts both classical\n// (x25519) and hybrid (mlkem768x25519) records. Returns the discriminated\n// UnwrapResult; it never throws on an authentication failure (wrong key,\n// tampered header, tampered ciphertext) — callers branch on `result.matched`.\nexport function decryptSealedFromSeed(args: DecryptSealedFromSeedArgs): UnwrapResult {\n return eciesSealedPoeUnwrap({\n envelope: args.envelope,\n ciphertext: args.ciphertext,\n recipientKeyBundle: recipientKeyBundleFromSeed(args.seed),\n });\n}\n"]}
1
+ {"version":3,"sources":["../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/utils.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/_crystals.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/ml-kem.ts","../../../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/src/hybrid.ts","../../../crypto-core/src/kdf/hkdf.ts","../../../crypto-core/src/kem/mlkem768x25519.ts","../../../crypto-core/src/kem/x25519.ts","../../../crypto-core/src/sig/ed25519.ts","../../../crypto-core/src/seed-derive/errors.ts","../../../crypto-core/src/seed-derive/derive.ts","../../../crypto-core/src/recipient/bech32.ts","../../../crypto-core/src/recipient/age-recipient.ts","../../../crypto-core/src/aead/errors.ts","../../../crypto-core/src/aead/chacha20-poly1305.ts","../../../crypto-core/src/sealed-poe/errors.ts","../../../crypto-core/src/sealed-poe/stream.ts","../../../crypto-core/src/cbor/canonical.ts","../../../crypto-core/src/sealed-poe/transcript.ts","../../../crypto-core/src/sealed-poe/wrap.ts","../../../crypto-core/src/util/compare-ct.ts","../../../crypto-core/src/sealed-poe/slot-acceptance.ts","../../../crypto-core/src/sealed-poe/unwrap.ts","../../../crypto-core/src/sealed-poe/passphrase-normalize.ts","../../src/identity/seed-identity.ts"],"names":["abytes","randb","abytes_","opts","N","Q","F","ROOT_OF_UNITY","reverseBits","FFTCore","shake128","u32","swap32IfBE","shake256","sha3_256","sha3_512","bytesToNumberLE","bytesToNumberBE","anumber","x25519","concatBytes","asciiToBytes","hkdf","sha256","ed","sha512","chacha20poly1305","MLKEM768X25519_SEED_LENGTH","mlkem768x25519Keygen","x25519PublicKey","hkdfSha256","encode","sortCoreDeterministic","EMPTY_SALT","hashes","hmac","CEK_LENGTH","ZERO_NONCE_12","X25519_SECRET_KEY_LENGTH","X25519_PUBLIC_KEY_LENGTH","NONCE_LENGTH","WRAP_LENGTH","SLOTS_MAC_LENGTH","ed2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Utilities for hex, bytearray and number handling.\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport {\n type CHash,\n type TypedArray,\n abytes,\n abytes as abytes_,\n concatBytes,\n isLE,\n randomBytes as randb,\n} from '@noble/hashes/utils.js';\n/**\n * Bytes API type helpers for old + new TypeScript.\n *\n * TS 5.6 has `Uint8Array`, while TS 5.9+ made it generic `Uint8Array<ArrayBuffer>`.\n * We can't use specific return type, because TS 5.6 will error.\n * We can't use generic return type, because most TS 5.9 software will expect specific type.\n *\n * Maps typed-array input leaves to broad forms.\n * These are compatibility adapters, not ownership guarantees.\n *\n * - `TArg` keeps byte inputs broad.\n * - `TRet` marks byte outputs for TS 5.6 and TS 5.9+ compatibility.\n */\nexport type TypedArg<T> = T extends BigInt64Array\n ? BigInt64Array\n : T extends BigUint64Array\n ? BigUint64Array\n : T extends Float32Array\n ? Float32Array\n : T extends Float64Array\n ? Float64Array\n : T extends Int16Array\n ? Int16Array\n : T extends Int32Array\n ? Int32Array\n : T extends Int8Array\n ? Int8Array\n : T extends Uint16Array\n ? Uint16Array\n : T extends Uint32Array\n ? Uint32Array\n : T extends Uint8ClampedArray\n ? Uint8ClampedArray\n : T extends Uint8Array\n ? Uint8Array\n : never;\n/** Maps typed-array output leaves to narrow TS-compatible forms. */\nexport type TypedRet<T> = T extends BigInt64Array\n ? ReturnType<typeof BigInt64Array.of>\n : T extends BigUint64Array\n ? ReturnType<typeof BigUint64Array.of>\n : T extends Float32Array\n ? ReturnType<typeof Float32Array.of>\n : T extends Float64Array\n ? ReturnType<typeof Float64Array.of>\n : T extends Int16Array\n ? ReturnType<typeof Int16Array.of>\n : T extends Int32Array\n ? ReturnType<typeof Int32Array.of>\n : T extends Int8Array\n ? ReturnType<typeof Int8Array.of>\n : T extends Uint16Array\n ? ReturnType<typeof Uint16Array.of>\n : T extends Uint32Array\n ? ReturnType<typeof Uint32Array.of>\n : T extends Uint8ClampedArray\n ? ReturnType<typeof Uint8ClampedArray.of>\n : T extends Uint8Array\n ? ReturnType<typeof Uint8Array.of>\n : never;\n/** Recursively adapts byte-carrying API input types. See {@link TypedArg}. */\nexport type TArg<T> =\n | T\n | ([TypedArg<T>] extends [never]\n ? T extends (...args: infer A) => infer R\n ? ((...args: { [K in keyof A]: TRet<A[K]> }) => TArg<R>) & {\n [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TArg<T[K]>;\n }\n : T extends [infer A, ...infer R]\n ? [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]\n : T extends readonly [infer A, ...infer R]\n ? readonly [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]\n : T extends (infer A)[]\n ? TArg<A>[]\n : T extends readonly (infer A)[]\n ? readonly TArg<A>[]\n : T extends Promise<infer A>\n ? Promise<TArg<A>>\n : T extends object\n ? { [K in keyof T]: TArg<T[K]> }\n : T\n : TypedArg<T>);\n/** Recursively adapts byte-carrying API output types. See {@link TypedArg}. */\nexport type TRet<T> = T extends unknown\n ? T &\n ([TypedRet<T>] extends [never]\n ? T extends (...args: infer A) => infer R\n ? ((...args: { [K in keyof A]: TArg<A[K]> }) => TRet<R>) & {\n [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TRet<T[K]>;\n }\n : T extends [infer A, ...infer R]\n ? [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]\n : T extends readonly [infer A, ...infer R]\n ? readonly [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]\n : T extends (infer A)[]\n ? TRet<A>[]\n : T extends readonly (infer A)[]\n ? readonly TRet<A>[]\n : T extends Promise<infer A>\n ? Promise<TRet<A>>\n : T extends object\n ? { [K in keyof T]: TRet<T[K]> }\n : T\n : TypedRet<T>)\n : never;\n/**\n * Asserts that a value is a byte array and optionally checks its length.\n * Returns the original reference unchanged on success, and currently also accepts Node `Buffer`\n * values through the upstream validator.\n * This helper throws on malformed input, so APIs that must return `false` need to guard lengths\n * before decoding or before calling it.\n * @example\n * Validate that a value is a byte array with the expected length.\n * ```ts\n * abytes(new Uint8Array([1]), 1);\n * ```\n */\nconst abytesDoc: typeof abytes = abytes;\nexport { abytesDoc as abytes };\n/**\n * Concatenates byte arrays into a new `Uint8Array`.\n * Zero arguments return an empty `Uint8Array`.\n * Invalid segments throw before allocation because each argument is validated first.\n * @example\n * Concatenate two byte arrays into one result.\n * ```ts\n * concatBytes(new Uint8Array([1]), new Uint8Array([2]));\n * ```\n */\nconst concatBytesDoc: typeof concatBytes = concatBytes;\nexport { concatBytesDoc as concatBytes };\n/**\n * Returns cryptographically secure random bytes.\n * Requires `globalThis.crypto.getRandomValues` and throws if that API is unavailable.\n * `bytesLength` is validated by the upstream helper as a non-negative integer before allocation,\n * so negative and fractional values both throw instead of truncating through JS `ToIndex`.\n * @param bytesLength - Number of random bytes to generate.\n * @returns Fresh random bytes.\n * @example\n * Generate a fresh random seed.\n * ```ts\n * const seed = randomBytes(4);\n * ```\n */\nexport const randomBytes: typeof randb = randb;\n\n/**\n * Compares two byte arrays in a length-constant way for equal lengths.\n * Unequal lengths return `false` immediately, and there is no runtime type validation.\n * @param a - First byte array.\n * @param b - Second byte array.\n * @returns Whether both arrays contain the same bytes.\n * @example\n * Compare two byte arrays for equality.\n * ```ts\n * equalBytes(new Uint8Array([1]), new Uint8Array([1]));\n * ```\n */\nexport function equalBytes(a: TArg<Uint8Array>, b: TArg<Uint8Array>): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n\n/**\n * Copies bytes into a fresh `Uint8Array`.\n * Returns a detached plain `Uint8Array` after validating that the input is real bytes.\n * @param bytes - Source bytes.\n * @returns Copy of the input bytes.\n * @example\n * Copy bytes into a fresh array.\n * ```ts\n * copyBytes(new Uint8Array([1, 2]));\n * ```\n */\nexport function copyBytes(bytes: TArg<Uint8Array>): TRet<Uint8Array> {\n // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict\n // because callers use it at byte-validation boundaries before mutating the detached copy.\n return Uint8Array.from(abytes(bytes)) as TRet<Uint8Array>;\n}\n\n/**\n * Byte-swaps each 64-bit lane in place.\n * Falcon's exact binary64 tables are stored as little-endian byte payloads, so BE runtimes need\n * this boundary helper before aliasing them as host `Float64Array` lanes.\n * @param arr - Byte buffer whose length is a multiple of 8.\n * @returns The same buffer after in-place 64-bit lane byte swaps.\n * @example\n * Byte-swap one 64-bit lane in place.\n * ```ts\n * byteSwap64(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]));\n * ```\n */\nexport function byteSwap64<T extends ArrayBufferView>(arr: T): T {\n const bytes = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n for (let i = 0; i < bytes.length; i += 8) {\n const a0 = bytes[i + 0];\n const a1 = bytes[i + 1];\n const a2 = bytes[i + 2];\n const a3 = bytes[i + 3];\n bytes[i + 0] = bytes[i + 7];\n bytes[i + 1] = bytes[i + 6];\n bytes[i + 2] = bytes[i + 5];\n bytes[i + 3] = bytes[i + 4];\n bytes[i + 4] = a3;\n bytes[i + 5] = a2;\n bytes[i + 6] = a1;\n bytes[i + 7] = a0;\n }\n return arr;\n}\n/**\n * Byte-swaps 64-bit lanes on big-endian runtimes and returns the input unchanged on little-endian.\n * This keeps Falcon's binary64 tables in canonical little-endian order before aliasing them as\n * `Float64Array` lanes on the current host.\n * @param arr - Buffer to pass through or swap in place.\n * @returns The same buffer, normalized for Falcon's little-endian table layout.\n * @example\n * Normalize one host-endian buffer for Falcon's float tables.\n * ```ts\n * baswap64If(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]));\n * ```\n */\nexport const baswap64If: <T extends ArrayBufferView>(arr: T) => T = isLE\n ? (arr) => arr\n : byteSwap64;\n\n/** Shared key-generation surface for signers and KEMs. */\nexport type CryptoKeys = {\n /** Optional metadata about the algorithm family or variant. */\n info?: { type?: string };\n /** Public byte lengths for the exported key material. */\n lengths: { seed?: number; publicKey?: number; secretKey?: number };\n /**\n * Generate one secret/public keypair.\n * @param seed - Optional seed bytes for deterministic key generation.\n * @returns Fresh secret/public keypair.\n */\n keygen: (seed?: TArg<Uint8Array>) => {\n secretKey: TRet<Uint8Array>;\n publicKey: TRet<Uint8Array>;\n };\n /**\n * Derive one public key from a secret key.\n * @param secretKey - Secret key bytes.\n * @returns Public key bytes.\n */\n getPublicKey: (secretKey: TArg<Uint8Array>) => TRet<Uint8Array>;\n};\n\n/** Verification options shared by the signature APIs. */\nexport type VerOpts = {\n /** Optional application-defined context string. */\n context?: Uint8Array;\n};\n/** Signing options shared by the signature APIs. */\nexport type SigOpts = VerOpts & {\n // Compatibility with @noble/curves: false to disable, enabled by default, user can pass U8A\n /** Optional extra entropy or `false` to disable randomized signing. */\n extraEntropy?: Uint8Array | false;\n};\n\n/**\n * Validates that an options bag is a plain object.\n * @param opts - Options object to validate.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate that an options bag is a plain object.\n * ```ts\n * validateOpts({});\n * ```\n */\nexport function validateOpts(opts: object): void {\n // Arrays silently passed here before, but these call sites expect named option-bag fields.\n if (Object.prototype.toString.call(opts) !== '[object Object]')\n throw new TypeError('expected valid options object');\n}\n\n/**\n * Validates common verification options.\n * `context` itself is validated with `abytes(...)`, and individual algorithms may narrow support\n * further after this shared plain-object gate.\n * @param opts - Verification options. See {@link VerOpts}.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate common verification options.\n * ```ts\n * validateVerOpts({ context: new Uint8Array([1]) });\n * ```\n */\nexport function validateVerOpts(opts: TArg<VerOpts>): void {\n validateOpts(opts);\n if (opts.context !== undefined) abytes(opts.context, undefined, 'opts.context');\n}\n\n/**\n * Validates common signing options.\n * `extraEntropy` is validated with `abytes(...)`; exact lengths and extra algorithm-specific\n * restrictions are enforced later by callers.\n * @param opts - Signing options. See {@link SigOpts}.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validate common signing options.\n * ```ts\n * validateSigOpts({ extraEntropy: new Uint8Array([1]) });\n * ```\n */\nexport function validateSigOpts(opts: TArg<SigOpts>): void {\n validateVerOpts(opts);\n if (opts.extraEntropy !== false && opts.extraEntropy !== undefined)\n abytes(opts.extraEntropy, undefined, 'opts.extraEntropy');\n}\n\n/** Generic signature interface with key generation, signing, and verification. */\nexport type Signer = CryptoKeys & {\n /** Public byte lengths for signatures and signing randomness. */\n lengths: { signRand?: number; signature?: number };\n /**\n * Sign one message.\n * @param msg - Message bytes to sign.\n * @param secretKey - Secret key bytes.\n * @param opts - Optional signing options.\n * @returns Signature bytes.\n */\n sign: (\n msg: TArg<Uint8Array>,\n secretKey: TArg<Uint8Array>,\n opts?: TArg<SigOpts>\n ) => TRet<Uint8Array>;\n /**\n * Verify one signature.\n * @param sig - Signature bytes.\n * @param msg - Signed message bytes.\n * @param publicKey - Public key bytes.\n * @param opts - Optional verification options.\n * @returns `true` when the signature is valid, `false` when all inputs are well-formed but the\n * signature check does not pass. Some implementations also treat malformed signature encodings as\n * a verification failure and return `false`.\n * @throws On malformed API arguments or unsupported verification options.\n */\n verify: (\n sig: TArg<Uint8Array>,\n msg: TArg<Uint8Array>,\n publicKey: TArg<Uint8Array>,\n opts?: TArg<VerOpts>\n ) => boolean;\n};\n\n/** Generic key encapsulation mechanism interface. */\nexport type KEM = CryptoKeys & {\n /** Public byte lengths for ciphertexts and optional message randomness. */\n lengths: { cipherText?: number; msg?: number; msgRand?: number };\n /**\n * Encapsulate one shared secret to a recipient public key.\n * @param publicKey - Recipient public key bytes.\n * @param msg - Optional caller-provided randomness/message seed.\n * @returns Ciphertext plus shared secret.\n */\n encapsulate: (\n publicKey: TArg<Uint8Array>,\n msg?: TArg<Uint8Array>\n ) => {\n cipherText: TRet<Uint8Array>;\n sharedSecret: TRet<Uint8Array>;\n };\n /**\n * Recover the shared secret from a ciphertext and recipient secret key.\n * @param cipherText - Ciphertext bytes.\n * @param secretKey - Recipient secret key bytes.\n * @returns Decapsulated shared secret.\n */\n decapsulate: (cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) => TRet<Uint8Array>;\n};\n\n/** Bidirectional encoder/decoder interface. */\nexport interface Coder<F, T> {\n /**\n * Serialize one value.\n * @param from - Value to encode.\n * @returns Encoded representation.\n */\n encode(from: F): T;\n /**\n * Parse one serialized value.\n * @param to - Encoded representation.\n * @returns Decoded value.\n */\n decode(to: T): F;\n}\n\n/** Encoder/decoder interface specialized for byte arrays. */\nexport interface BytesCoder<T> extends Coder<T, Uint8Array> {\n /**\n * Serialize one value into bytes.\n * @param data - Value to encode.\n * @returns Encoded bytes.\n */\n encode: (data: T) => Uint8Array;\n /**\n * Parse one byte array into a value.\n * @param bytes - Encoded bytes.\n * @returns Decoded value.\n */\n decode: (bytes: Uint8Array) => T;\n}\n\n/** Fixed-length byte encoder/decoder. */\nexport type BytesCoderLen<T> = BytesCoder<T> & { bytesLen: number };\n\n// nano-packed, because struct encoding is hard.\ntype UnCoder<T> = T extends BytesCoder<infer U> ? U : never;\ntype SplitOut<T extends (number | BytesCoderLen<any>)[]> = {\n [K in keyof T]: T[K] extends number ? Uint8Array : UnCoder<T[K]>;\n};\n/**\n * Builds a fixed-layout coder from byte lengths and nested coders.\n * Raw-length fields decode as zero-copy `subarray(...)` views, and nested coders may preserve that\n * aliasing too. Nested coder `encode(...)` results are treated as owned scratch: `splitCoder`\n * copies them into the output and then zeroizes them with `fill(0)`. If a nested encoder forwards\n * caller-owned bytes, it must do so only after detaching them into a disposable copy.\n * @param label - Label used in validation errors.\n * @param lengths - Field lengths or nested coders.\n * @returns Composite fixed-length coder.\n * @example\n * Build a fixed-layout coder from byte lengths and nested coders.\n * ```ts\n * splitCoder('demo', 1, 2).encode([new Uint8Array([1]), new Uint8Array([2, 3])]);\n * ```\n */\nexport function splitCoder<T extends (number | BytesCoderLen<any>)[]>(\n label: string,\n ...lengths: T\n): TRet<BytesCoder<SplitOut<T>> & { bytesLen: number }> {\n const getLength = (c: TArg<number | BytesCoderLen<any>>) =>\n typeof c === 'number' ? c : (c as BytesCoderLen<any>).bytesLen;\n const bytesLen: number = lengths.reduce((sum: number, a) => sum + getLength(a), 0);\n return {\n bytesLen,\n encode: (bufs: T) => {\n const res = new Uint8Array(bytesLen);\n for (let i = 0, pos = 0; i < lengths.length; i++) {\n const c = lengths[i];\n const l = getLength(c);\n const b: Uint8Array = typeof c === 'number' ? (bufs[i] as any) : c.encode(bufs[i]);\n abytes_(b, l, label);\n res.set(b, pos);\n if (typeof c !== 'number') b.fill(0); // clean\n pos += l;\n }\n return res;\n },\n decode: (buf: TArg<Uint8Array>) => {\n abytes_(buf, bytesLen, label);\n const res = [];\n for (const c of lengths) {\n const l = getLength(c);\n const b = buf.subarray(0, l);\n res.push(typeof c === 'number' ? b : c.decode(b));\n buf = buf.subarray(l);\n }\n return res as SplitOut<T>;\n },\n } as any;\n}\n// nano-packed.array (fixed size)\n/**\n * Builds a fixed-length vector coder from another fixed-length coder.\n * Element decoding receives `subarray(...)` views, so aliasing depends on the element coder.\n * Element coder `encode(...)` results are treated as owned scratch: `vecCoder` copies them into\n * the output and then zeroizes them with `fill(0)`. If an element encoder forwards caller-owned\n * bytes, it must do so only after detaching them into a disposable copy. `vecCoder` also trusts\n * the `BytesCoderLen` contract: each encoded element must already be exactly `c.bytesLen` bytes.\n * @param c - Element coder.\n * @param vecLen - Number of elements in the vector.\n * @returns Fixed-length vector coder.\n * @example\n * Build a fixed-length vector coder from another fixed-length coder.\n * ```ts\n * vecCoder(\n * { bytesLen: 1, encode: (n: number) => Uint8Array.of(n), decode: (b: Uint8Array) => b[0] || 0 },\n * 2\n * ).encode([1, 2]);\n * ```\n */\nexport function vecCoder<T>(c: TArg<BytesCoderLen<T>>, vecLen: number): TRet<BytesCoderLen<T[]>> {\n const coder = c as BytesCoderLen<T>;\n const bytesLen = vecLen * coder.bytesLen;\n return {\n bytesLen,\n encode: (u: TArg<T[]>): TRet<Uint8Array> => {\n if (u.length !== vecLen)\n throw new RangeError(`vecCoder.encode: wrong length=${u.length}. Expected: ${vecLen}`);\n const res = new Uint8Array(bytesLen);\n for (let i = 0, pos = 0; i < u.length; i++) {\n const b = coder.encode(u[i] as T);\n res.set(b, pos);\n b.fill(0); // clean\n pos += b.length;\n }\n return res as TRet<Uint8Array>;\n },\n decode: (a: TArg<Uint8Array>): TRet<T[]> => {\n abytes_(a, bytesLen);\n const r: T[] = [];\n for (let i = 0; i < a.length; i += coder.bytesLen)\n r.push(coder.decode(a.subarray(i, i + coder.bytesLen)));\n return r as TRet<T[]>;\n },\n } as any;\n}\n\n/**\n * Overwrites supported typed-array inputs with zeroes in place.\n * Accepts direct typed arrays and one-level arrays of them.\n * @param list - Typed arrays or one-level lists of typed arrays to clear.\n * @example\n * Overwrite typed arrays with zeroes.\n * ```ts\n * const buf = Uint8Array.of(1, 2, 3);\n * cleanBytes(buf);\n * ```\n */\nexport function cleanBytes(...list: (TypedArray | TypedArray[])[]): void {\n for (const t of list) {\n if (Array.isArray(t)) for (const b of t) b.fill(0);\n else t.fill(0);\n }\n}\n\n/**\n * Creates a 32-bit mask with the lowest `bits` bits set.\n * @param bits - Number of low bits to keep.\n * @returns Bit mask with `bits` ones.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Create a low-bit mask for packed-field operations.\n * ```ts\n * const mask = getMask(4);\n * ```\n */\nexport function getMask(bits: number): number {\n if (!Number.isSafeInteger(bits) || bits < 0 || bits > 32)\n throw new RangeError(`expected bits in [0..32], got ${bits}`);\n // JS shifts are modulo 32, so bit 32 needs an explicit full-width mask.\n return bits === 32 ? 0xffffffff : ~(-1 << bits) >>> 0;\n}\n\n/** Shared empty byte array used as the default context. */\nexport const EMPTY: TRet<Uint8Array> = /* @__PURE__ */ Uint8Array.of();\n\n/**\n * Builds the domain-separated message payload for the pure sign/verify paths.\n * Context length `255` is valid; only `ctx.length > 255` is rejected.\n * @param msg - Message bytes.\n * @param ctx - Optional context bytes.\n * @returns Domain-separated message payload.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Build the domain-separated payload before direct signing.\n * ```ts\n * const payload = getMessage(new Uint8Array([1, 2]));\n * ```\n */\nexport function getMessage(msg: TArg<Uint8Array>, ctx: TArg<Uint8Array> = EMPTY): TRet<Uint8Array> {\n abytes_(msg);\n abytes_(ctx);\n if (ctx.length > 255) throw new RangeError('context should be 255 bytes or less');\n return concatBytes(new Uint8Array([0, ctx.length]), ctx, msg);\n}\n\n// DER tag+length plus the shared NIST hash OID arc 2.16.840.1.101.3.4.2.* used by the\n// FIPS 204 / FIPS 205 pre-hash wrappers; the final byte selects SHA-256, SHA-512, SHAKE128,\n// SHAKE256, or another approved hash/XOF under that subtree.\n// 06 09 60 86 48 01 65 03 04 02\nconst oidNistP = /* @__PURE__ */ Uint8Array.from([6, 9, 0x60, 0x86, 0x48, 1, 0x65, 3, 4, 2]);\n\n/**\n * Validates that a hash exposes a NIST hash OID and enough collision resistance.\n * Current accepted surface is broader than the FIPS algorithm tables: any hash/XOF under the NIST\n * `2.16.840.1.101.3.4.2.*` subtree is accepted if its effective `outputLen` is strong enough.\n * XOF callers must pass a callable whose `outputLen` matches the digest length they actually intend\n * to sign; bare `shake128` / `shake256` defaults are too short for the stronger prehash modes.\n * @param hash - Hash function to validate.\n * @param requiredStrength - Minimum required collision-resistance strength in bits.\n * @throws If the hash metadata or collision resistance is insufficient. {@link Error}\n * @example\n * Validate that a hash exposes a NIST hash OID and enough collision resistance.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { checkHash } from '@noble/post-quantum/utils.js';\n * checkHash(sha256, 128);\n * ```\n */\nexport function checkHash(hash: CHash, requiredStrength: number = 0): void {\n if (!hash.oid || !equalBytes(hash.oid.subarray(0, 10), oidNistP))\n throw new Error('hash.oid is invalid: expected NIST hash');\n // FIPS 204 / FIPS 205 require both collision and second-preimage strength; for approved NIST\n // hashes/XOFs under this OID subtree, the collision bound from the configured digest length is\n // the tighter runtime check, so enforce that lower bound here.\n const collisionResistance = (hash.outputLen * 8) / 2;\n if (requiredStrength > collisionResistance) {\n throw new Error(\n 'Pre-hash security strength too low: ' +\n collisionResistance +\n ', required: ' +\n requiredStrength\n );\n }\n}\n\n/**\n * Builds the domain-separated prehash payload for the prehash sign/verify paths.\n * Callers are expected to vet `hash.oid` first, e.g. via `checkHash(...)`; calling this helper\n * directly with a hash object that lacks `oid` currently throws later inside `concatBytes(...)`.\n * Context length `255` is valid; only `ctx.length > 255` is rejected.\n * @param hash - Prehash function.\n * @param msg - Message bytes.\n * @param ctx - Optional context bytes.\n * @returns Domain-separated prehash payload.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Build the domain-separated prehash payload for external hashing.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { getMessagePrehash } from '@noble/post-quantum/utils.js';\n * getMessagePrehash(sha256, new Uint8Array([1, 2]));\n * ```\n */\nexport function getMessagePrehash(\n hash: CHash,\n msg: TArg<Uint8Array>,\n ctx: TArg<Uint8Array> = EMPTY\n): TRet<Uint8Array> {\n abytes_(msg);\n abytes_(ctx);\n if (ctx.length > 255) throw new RangeError('context should be 255 bytes or less');\n const hashed = hash(msg);\n return concatBytes(new Uint8Array([1, ctx.length]), ctx, hash.oid!, hashed);\n}\n","/**\n * Internal methods for lattice-based ML-KEM and ML-DSA.\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { FFTCore, reverseBits } from '@noble/curves/abstract/fft.js';\nimport { shake128, shake256 } from '@noble/hashes/sha3.js';\nimport type { TypedArray } from '@noble/hashes/utils.js';\nimport {\n type BytesCoderLen,\n cleanBytes,\n type Coder,\n getMask,\n type TArg,\n type TRet,\n} from './utils.ts';\n\n/** Extendable-output reader used by the CRYSTALS implementations. */\nexport type XOF = (\n seed: Uint8Array,\n blockLen?: number\n) => {\n /**\n * Read diagnostic counters for the current XOF session.\n * @returns Current call and XOF block counters.\n */\n stats: () => { calls: number; xofs: number };\n /**\n * Select one `(x, y)` coordinate pair and get a block reader for it.\n * Only one coordinate stream is live at a time: a later `get(...)` call rebinds the shared\n * SHAKE state and invalidates older readers.\n * Each squeeze aliases one mutable internal output buffer, so callers must copy blocks they\n * want to retain before the next read.\n * @param x - First matrix coordinate.\n * @param y - Second matrix coordinate.\n * @returns Lazy block reader for that coordinate pair.\n */\n get: (x: number, y: number) => () => Uint8Array; // return block aligned to blockLen and 3\n /** Wipe any buffered state once the reader is no longer needed. */\n clean: () => void;\n};\n\n/** CRYSTALS (ml-kem, ml-dsa) options */\n/** Shared polynomial and NTT parameters for CRYSTALS algorithms. */\nexport type CrystalOpts<T extends TypedArray> = {\n /**\n * Allocate one zeroed polynomial/vector container.\n * @param n - Number of coefficients to allocate.\n * @returns Fresh typed container.\n */\n newPoly: TypedCons<T>;\n /** Polynomial size, typically `256`. */\n N: number;\n /** Prime modulus used for all coefficient arithmetic. */\n Q: number;\n /** Inverse transform normalization factor:\n * `256**-1 mod q` for Dilithium, `128**-1 mod q` for Kyber.\n */\n F: number;\n /** Principal root of unity for the transform domain. */\n ROOT_OF_UNITY: number;\n /** Number of bits used for bit-reversal ordering. */\n brvBits: number;\n /** `true` for Kyber/ML-KEM mode, `false` for Dilithium/ML-DSA mode. */\n isKyber: boolean;\n};\n\n/** Constructor function for typed polynomial containers. */\nexport type TypedCons<T extends TypedArray> = (n: number) => T;\n\ntype Crystals<T extends TypedArray> = {\n mod: (a: number, modulo?: number) => number;\n smod: (a: number, modulo?: number) => number;\n nttZetas: T;\n NTT: {\n /** Forward transform in place. Mutates and returns `r`. */\n encode: (r: T) => T;\n /** Inverse transform in place. Mutates and returns `r`. */\n decode: (r: T) => T;\n };\n bitsCoder: (d: number, c: Coder<number, number>) => BytesCoderLen<T>;\n};\n\n/**\n * Creates shared modular arithmetic, NTT, and packing helpers for CRYSTALS schemes.\n * @param opts - Polynomial and transform parameters. See {@link CrystalOpts}.\n * @returns CRYSTALS arithmetic and encoding helpers.\n * @example\n * Create shared modular arithmetic and NTT helpers for a CRYSTALS parameter set.\n * ```ts\n * const crystals = genCrystals({\n * newPoly: (n) => new Uint16Array(n),\n * N: 256,\n * Q: 3329,\n * F: 3303,\n * ROOT_OF_UNITY: 17,\n * brvBits: 7,\n * isKyber: true,\n * });\n * const reduced = crystals.mod(-1);\n * ```\n */\nexport const genCrystals = <T extends TypedArray>(opts: CrystalOpts<T>): TRet<Crystals<T>> => {\n // isKyber: true means Kyber, false means Dilithium\n const { newPoly, N, Q, F, ROOT_OF_UNITY, brvBits, isKyber } = opts;\n // Normalize JS `%` into the canonical Z_m representative `[0, modulo-1]` expected by\n // FIPS 203 §2.3 / FIPS 204 §2.3 before downstream mod-q arithmetic.\n const mod = (a: number, modulo = Q): number => {\n const result = a % modulo | 0;\n return (result >= 0 ? result | 0 : (modulo + result) | 0) | 0;\n };\n // FIPS 204 §7.4 uses the centered `mod ±` representative for low bits, keeping the\n // positive midpoint when `modulo` is even.\n // Center to `[-floor((modulo-1)/2), floor(modulo/2)]`.\n const smod = (a: number, modulo = Q): number => {\n const r = mod(a, modulo) | 0;\n return (r > modulo >> 1 ? (r - modulo) | 0 : r) | 0;\n };\n // Kyber uses the FIPS 203 Appendix A `BitRev_7` table here via the first 128 entries, while\n // Dilithium uses the FIPS 204 §7.5 / Appendix B `BitRev_8` zetas table over all 256 entries.\n function getZettas() {\n const out = newPoly(N);\n for (let i = 0; i < N; i++) {\n const b = reverseBits(i, brvBits);\n const p = BigInt(ROOT_OF_UNITY) ** BigInt(b) % BigInt(Q);\n out[i] = Number(p) | 0;\n }\n return out;\n }\n const nttZetas = getZettas();\n\n // Number-Theoretic Transform\n // Explained: https://electricdusk.com/ntt.html\n\n // Kyber has slightly different params, since there is no 512th primitive root of unity mod q,\n // only 256th primitive root of unity mod. Which also complicates MultiplyNTT.\n\n const field = {\n add: (a: number, b: number) => mod((a | 0) + (b | 0)) | 0,\n sub: (a: number, b: number) => mod((a | 0) - (b | 0)) | 0,\n mul: (a: number, b: number) => mod((a | 0) * (b | 0)) | 0,\n inv: (_a: number) => {\n throw new Error('not implemented');\n },\n };\n const nttOpts = {\n N,\n roots: nttZetas as any,\n invertButterflies: true,\n skipStages: isKyber ? 1 : 0,\n brp: false,\n };\n const dif = FFTCore(field, { dit: false, ...nttOpts });\n const dit = FFTCore(field, { dit: true, ...nttOpts });\n const NTT = {\n encode: (r: T): T => {\n return dif(r) as any;\n },\n decode: (r: T): T => {\n dit(r as any);\n // The inverse-NTT normalization factor is family-specific: FIPS 203 Algorithm 10 line 14\n // uses `128^-1 mod q` for Kyber, while FIPS 204 Algorithm 42 lines 21-23 use `256^-1 mod q`.\n // kyber uses 128 here, because brv && stuff\n for (let i = 0; i < r.length; i++) r[i] = mod(F * r[i]);\n return r;\n },\n };\n // Pack one little-endian `d`-bit word per coefficient, matching FIPS 203 ByteEncode /\n // ByteDecode and the FIPS 204 BitsToBytes-based polynomial packing helpers.\n const bitsCoder = (d: number, c: Coder<number, number>): TRet<BytesCoderLen<T>> => {\n const mask = getMask(d);\n const bytesLen = d * (N / 8);\n return {\n bytesLen,\n encode: (poly_: TArg<T>): TRet<Uint8Array> => {\n const poly = poly_ as T;\n const r = new Uint8Array(bytesLen);\n for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < poly.length; i++) {\n buf |= (c.encode(poly[i]) & mask) << bufLen;\n bufLen += d;\n for (; bufLen >= 8; bufLen -= 8, buf >>= 8) r[pos++] = buf & getMask(bufLen);\n }\n return r as TRet<Uint8Array>;\n },\n decode: (bytes: TArg<Uint8Array>): TRet<T> => {\n const r = newPoly(N);\n for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < bytes.length; i++) {\n buf |= bytes[i] << bufLen;\n bufLen += 8;\n for (; bufLen >= d; bufLen -= d, buf >>= d) r[pos++] = c.decode(buf & mask);\n }\n return r as TRet<T>;\n },\n } as TRet<BytesCoderLen<T>>;\n };\n\n return {\n mod,\n smod,\n nttZetas: nttZetas as TRet<T>,\n NTT: {\n encode: (r: TArg<T>): TRet<T> => NTT.encode(r as T) as TRet<T>,\n decode: (r: TArg<T>): TRet<T> => NTT.decode(r as T) as TRet<T>,\n },\n bitsCoder: bitsCoder as TRet<Crystals<T>>['bitsCoder'],\n };\n};\n\nconst createXofShake =\n (shake: typeof shake128): TRet<XOF> =>\n (seed: TArg<Uint8Array>, blockLen?: number) => {\n if (!blockLen) blockLen = shake.blockLen;\n // Optimizations that won't mater:\n // - cached seed update (two .update(), on start and on the end)\n // - another cache which cloned into working copy\n\n // Faster than multiple updates, since seed less than blockLen\n const _seed = new Uint8Array(seed.length + 2);\n _seed.set(seed);\n const seedLen = seed.length;\n const buf = new Uint8Array(blockLen); // == shake128.blockLen\n let h = shake.create({});\n let calls = 0;\n let xofs = 0;\n return {\n stats: () => ({ calls, xofs }),\n get: (x: number, y: number) => {\n // Rebind to `seed || x || y` so callers can implement the spec's per-coordinate\n // SHAKE inputs like `rho || j || i` and `rho || IntegerToBytes(counter, 2)`.\n _seed[seedLen + 0] = x;\n _seed[seedLen + 1] = y;\n h.destroy();\n h = shake.create({}).update(_seed);\n calls++;\n return () => {\n xofs++;\n return h.xofInto(buf) as TRet<Uint8Array>;\n };\n },\n clean: () => {\n h.destroy();\n cleanBytes(buf, _seed);\n },\n };\n };\n\n/**\n * SHAKE128-based extendable-output reader factory used by ML-KEM.\n * `get(x, y)` selects one coordinate pair at a time; calling it again invalidates previously\n * returned readers, and each squeeze reuses one mutable internal output buffer.\n * @param seed - Seed bytes for the reader.\n * @param blockLen - Optional output block length.\n * @returns Stateful XOF reader.\n * @example\n * Build the ML-KEM SHAKE128 matrix expander and read one block.\n * ```ts\n * import { randomBytes } from '@noble/post-quantum/utils.js';\n * import { XOF128 } from '@noble/post-quantum/_crystals.js';\n * const reader = XOF128(randomBytes(32));\n * const block = reader.get(0, 0)();\n * ```\n */\nexport const XOF128: TRet<XOF> = /* @__PURE__ */ createXofShake(shake128);\n/**\n * SHAKE256-based extendable-output reader factory used by ML-DSA.\n * `get(x, y)` appends raw one-byte coordinates to the seed, invalidates previously returned\n * readers, and reuses one mutable internal output buffer for each squeeze.\n * @param seed - Seed bytes for the reader.\n * @param blockLen - Optional output block length.\n * @returns Stateful XOF reader.\n * @example\n * Build the ML-DSA SHAKE256 coefficient expander and read one block.\n * ```ts\n * import { randomBytes } from '@noble/post-quantum/utils.js';\n * import { XOF256 } from '@noble/post-quantum/_crystals.js';\n * const reader = XOF256(randomBytes(32));\n * const block = reader.get(0, 0)();\n * ```\n */\nexport const XOF256: TRet<XOF> = /* @__PURE__ */ createXofShake(shake256);\n","/**\n * ML-KEM: Module Lattice-based Key Encapsulation Mechanism from\n * [FIPS-203](https://csrc.nist.gov/pubs/fips/203/ipd). A.k.a. CRYSTALS-Kyber.\n *\n * Key encapsulation is similar to DH / ECDH (think X25519), with important differences:\n * * Unlike in ECDH, we can't verify if it was \"Bob\" who've sent the shared secret\n * * Unlike ECDH, it is probabalistic and relies on quality of randomness (CSPRNG).\n * * Decapsulation never throws an error, even when shared secret was\n * encrypted by a different public key. It will just return a different shared secret.\n *\n * There are some concerns with regards to security: see\n * [djb blog](https://blog.cr.yp.to/20231003-countcorrectly.html) and\n * [mailing list](https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/W2VOzy0wz_E).\n *\n * Has similar internals to ML-DSA, but their keys and params are different.\n *\n * Check out [official site](https://www.pq-crystals.org/kyber/resources.shtml),\n * [repo](https://github.com/pq-crystals/kyber),\n * [spec](https://datatracker.ietf.org/doc/draft-cfrg-schwabe-kyber/).\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { sha3_256, sha3_512, shake256 } from '@noble/hashes/sha3.js';\nimport { type CHash, swap32IfBE, u32 } from '@noble/hashes/utils.js';\nimport { genCrystals, type XOF, XOF128 } from './_crystals.ts';\nimport {\n abytes,\n cleanBytes,\n type Coder,\n copyBytes,\n equalBytes,\n getMask,\n type KEM,\n randomBytes,\n splitCoder,\n type TArg,\n type TRet,\n vecCoder,\n} from './utils.ts';\n\n/** Key encapsulation mechanism interface */\n\nconst N = 256; // Kyber (not FIPS-203) supports different lengths, but all std modes were using 256\nconst Q = 3329; // 13*(2**8)+1, modulo prime\nconst F = 3303; // 3303 ≡ 128**(−1) mod q (FIPS-203)\nconst ROOT_OF_UNITY = 17; // ζ = 17 ∈ Zq is a primitive 256-th root of unity modulo Q. ζ**128 ≡−1\n// treeshake: keep genCrystals behind the object so PARAMS-only bundles can drop it entirely.\n// Shared CRYSTALS helper in the ML-KEM branch: Kyber mode, 7-bit bit-reversal,\n// and Uint16Array polys because current coefficients stay reduced modulo q.\nconst crystals = /* @__PURE__ */ genCrystals({\n N,\n Q,\n F,\n ROOT_OF_UNITY,\n newPoly: (n: number): TRet<Uint16Array> => new Uint16Array(n) as TRet<Uint16Array>,\n brvBits: 7,\n isKyber: true,\n});\n\n/** FIPS 203: 7. Parameter Sets */\n/** Public ML-KEM parameter-set description. */\nexport type KEMParam = {\n /** Polynomial size. */\n N: number;\n /** Module rank. */\n K: number;\n /** Prime modulus. */\n Q: number;\n /** CBD parameter used for secret-key noise. */\n ETA1: number;\n /** CBD parameter used for error noise. */\n ETA2: number;\n /** Compression width for the `u` vector. */\n du: number;\n /** Compression width for the `v` polynomial. */\n dv: number;\n /** Required strength of the randomness source in bits. */\n RBGstrength: number;\n};\n/** Internal params of ML-KEM versions */\n// prettier-ignore\n/** Built-in ML-KEM parameter presets keyed by the public export names\n * `ml_kem512` / `ml_kem768` / `ml_kem1024`.\n * `RBGstrength` is Table 2's required randomness-source strength in bits,\n * not a generic security label.\n */\nexport const PARAMS: Record<string, KEMParam> = /* @__PURE__ */ (() =>\n Object.freeze({\n 512: Object.freeze({ N, Q, K: 2, ETA1: 3, ETA2: 2, du: 10, dv: 4, RBGstrength: 128 }),\n 768: Object.freeze({ N, Q, K: 3, ETA1: 2, ETA2: 2, du: 10, dv: 4, RBGstrength: 192 }),\n 1024: Object.freeze({ N, Q, K: 4, ETA1: 2, ETA2: 2, du: 11, dv: 5, RBGstrength: 256 }),\n } as const))();\n\n// FIPS-203: compress/decompress\nconst compress = (d: number): Coder<number, number> => {\n // d=12 is the ByteEncode12/ByteDecode12 path, not lossy compression.\n // ByteDecode12 interprets each 12-bit word modulo q; without that reduction the public-key\n // modulus check in encapsulate() becomes a no-op for malformed coefficients like 4095.\n if (d >= 12) return { encode: (i: number) => i, decode: (i: number) => (i >= Q ? i - Q : i) };\n // Comments map to python implementation in RFC (draft-cfrg-schwabe-kyber)\n // const round = (i: number) => Math.floor(i + 0.5) | 0;\n const a = 2 ** (d - 1);\n return {\n // This only matches standalone Compress_d after bitsCoder masks the result into Z_(2^d).\n encode: (i: number) => ((i << d) + Q / 2) / Q,\n // const decompress = (i: number) => round((Q / 2 ** d) * i);\n decode: (i: number) => (i * Q + a) >>> d,\n };\n};\n\n// Raw ByteEncode_d / ByteDecode_d from FIPS 203 operate on d-bit words directly.\n// That differs from `polyCoder(d)` for d<12, where noble folds packing together with the lossy\n// ciphertext compression step used by u/v. Tests that exercise the spec's raw packing surface need\n// this exact non-lossy variant instead.\nconst byteCoder = (d: number) =>\n crystals.bitsCoder(\n d,\n d === 12\n ? { encode: (i: number) => i, decode: (i: number) => (i >= Q ? i - Q : i) }\n : { encode: (i: number) => i, decode: (i: number) => i }\n );\n\n// NOTE: we merge encoding and compress because it is faster, also both require same d param\n// d=12 is the ByteEncode12/ByteDecode12 path rather than compression, and caller-side\n// public-key modulus checks route through this helper's decode/encode roundtrip.\n// Converts between bytes and d-bits compressed representation.\n// Kinda like convertRadix2 from @scure/base.\n// decode(encode(t)) == t, but there is loss of information on encode(decode(t))\nconst polyCoder = (d: number) => (d === 12 ? byteCoder(12) : crystals.bitsCoder(d, compress(d)));\n\n// Poly is mod Q, so 12 bits\ntype Poly = Uint16Array;\n\nfunction polyAdd(a_: TArg<Poly>, b_: TArg<Poly>) {\n const a = a_ as Poly;\n const b = b_ as Poly;\n // Mutates `a` in place; callers must pass two N=256 polynomials.\n for (let i = 0; i < N; i++) a[i] = crystals.mod(a[i] + b[i]); // a += b\n}\nfunction polySub(a_: TArg<Poly>, b_: TArg<Poly>) {\n const a = a_ as Poly;\n const b = b_ as Poly;\n // Mutates `a` in place; callers must pass two N=256 polynomials.\n for (let i = 0; i < N; i++) a[i] = crystals.mod(a[i] - b[i]); // a -= b\n}\n\n// FIPS-203: Computes the product of two degree-one polynomials with respect to a quadratic modulus\nfunction BaseCaseMultiply(a0: number, a1: number, b0: number, b1: number, zeta: number) {\n // `zeta` here is Algorithm 11's γ = ζ^(2BitRev_7(i)+1).\n const c0 = crystals.mod(a1 * b1 * zeta + a0 * b0);\n const c1 = crystals.mod(a0 * b1 + a1 * b0);\n return { c0, c1 };\n}\n\n// FIPS-203: Computes the product (in the ring Tq) of two NTT representations.\n// Works in place on `f`; `g` is read-only and both inputs must already be in NTT form.\nfunction MultiplyNTTs(f_: TArg<Poly>, g_: TArg<Poly>): TRet<Poly> {\n const f = f_ as Poly;\n const g = g_ as Poly;\n for (let i = 0; i < N / 2; i++) {\n let z = crystals.nttZetas[64 + (i >> 1)];\n if (i & 1) z = -z;\n const { c0, c1 } = BaseCaseMultiply(f[2 * i + 0], f[2 * i + 1], g[2 * i + 0], g[2 * i + 1], z);\n f[2 * i + 0] = c0;\n f[2 * i + 1] = c1;\n }\n return f as TRet<Poly>;\n}\n\ntype PRF = (l: number, key: Uint8Array, nonce: number) => Uint8Array;\n\ntype XofGet = ReturnType<ReturnType<XOF>['get']>;\n\ntype KyberOpts = KEMParam & {\n HASH256: CHash;\n HASH512: CHash;\n KDF: CHash<any, { dkLen?: number }>;\n XOF: XOF; // (seed: Uint8Array, len: number, x: number, y: number) => Uint8Array;\n PRF: PRF;\n};\n\n// Return poly in NTT representation\nfunction SampleNTT(xof_: TArg<XofGet>): TRet<Poly> {\n const xof = xof_ as XofGet;\n // The reader must already bind the Algorithm 7 seed||j||i bytes\n // and return block lengths divisible by 3.\n const r: Poly = new Uint16Array(N);\n for (let j = 0; j < N; ) {\n const b = xof();\n if (b.length % 3) throw new Error('SampleNTT: unaligned block');\n for (let i = 0; j < N && i + 3 <= b.length; i += 3) {\n const d1 = ((b[i + 0] >> 0) | (b[i + 1] << 8)) & 0xfff;\n const d2 = ((b[i + 1] >> 4) | (b[i + 2] << 4)) & 0xfff;\n if (d1 < Q) r[j++] = d1;\n if (j < N && d2 < Q) r[j++] = d2;\n }\n }\n return r as TRet<Poly>;\n}\n\n// Sampling from the centered binomial distribution\n// Returns poly with small coefficients (noise/errors) stored modulo q in ordinary coefficient form.\n// Current callers only use Table 2 eta values {2,3} and PRF outputs of exactly 64*eta bytes.\nconst sampleCBDBytes = (buf: TArg<Uint8Array>, eta: number): TRet<Poly> => {\n const r: Poly = new Uint16Array(N);\n // CBD consumes the PRF bitstream in little-endian byte order; normalize the word view on BE,\n // then swap it back so callers still observe `buf` as read-only.\n const b32 = u32(buf);\n swap32IfBE(b32);\n let len = 0;\n for (let i = 0, p = 0, bb = 0, t0 = 0; i < b32.length; i++) {\n let b = b32[i];\n for (let j = 0; j < 32; j++) {\n bb += b & 1;\n b >>= 1;\n len += 1;\n if (len === eta) {\n t0 = bb;\n bb = 0;\n } else if (len === 2 * eta) {\n r[p++] = crystals.mod(t0 - bb);\n bb = 0;\n len = 0;\n }\n }\n }\n swap32IfBE(b32);\n if (len) throw new Error(`sampleCBD: leftover bits: ${len}`);\n return r as TRet<Poly>;\n};\n\nfunction sampleCBD(\n PRF_: TArg<PRF>,\n seed: TArg<Uint8Array>,\n nonce: number,\n eta: number\n): TRet<Poly> {\n const PRF = PRF_ as PRF;\n return sampleCBDBytes(PRF((eta * N) / 4, seed, nonce), eta);\n}\n\n// K-PKE\n// Internal ML-KEM subroutine only: exact 32-byte `seed` / `msg` inputs\n// come from Algorithms 13-15, and the helper mutates decoded temporary\n// polynomials in place while leaving caller byte arrays unchanged.\nconst genKPKE = (opts_: TArg<KyberOpts>) => {\n const opts = opts_ as KyberOpts;\n const { K, PRF, XOF, HASH512, ETA1, ETA2, du, dv } = opts;\n const poly1 = polyCoder(1);\n const polyV = polyCoder(dv);\n const polyU = polyCoder(du);\n const publicCoder = splitCoder('publicKey', vecCoder(polyCoder(12), K), 32);\n const secretCoder = vecCoder(polyCoder(12), K);\n const cipherCoder = splitCoder('ciphertext', vecCoder(polyU, K), polyV);\n const seedCoder = splitCoder('seed', 32, 32);\n return {\n secretCoder,\n lengths: {\n secretKey: secretCoder.bytesLen,\n publicKey: publicCoder.bytesLen,\n cipherText: cipherCoder.bytesLen,\n },\n keygen: (seed: TArg<Uint8Array>) => {\n abytes(seed, 32, 'seed');\n const seedDst = new Uint8Array(33);\n seedDst.set(seed);\n // FIPS 203 Algorithm 13 appends the parameter-set byte `k`\n // before `G(d || k)`, so expanding the same 32-byte seed\n // under a different ML-KEM parameter set yields unrelated keys.\n seedDst[32] = K;\n const seedHash = HASH512(seedDst);\n\n const [rho, sigma] = seedCoder.decode(seedHash);\n const sHat: Poly[] = [];\n const tHat: Poly[] = [];\n for (let i = 0; i < K; i++) sHat.push(crystals.NTT.encode(sampleCBD(PRF, sigma, i, ETA1)));\n const x = XOF(rho);\n for (let i = 0; i < K; i++) {\n const e = crystals.NTT.encode(sampleCBD(PRF, sigma, K + i, ETA1));\n for (let j = 0; j < K; j++) {\n const aji = SampleNTT(x.get(j, i)); // A[i][j], inplace\n polyAdd(e, MultiplyNTTs(aji, sHat[j]));\n }\n tHat.push(e); // t ← A ◦ s + e\n }\n x.clean();\n const res = {\n publicKey: publicCoder.encode([tHat, rho]),\n secretKey: secretCoder.encode(sHat),\n };\n cleanBytes(rho, sigma, sHat, tHat, seedDst, seedHash);\n return res;\n },\n encrypt: (\n publicKey: TArg<Uint8Array>,\n msg: TArg<Uint8Array>,\n seed: TArg<Uint8Array>\n ): TRet<Uint8Array> => {\n const [tHat, rho] = publicCoder.decode(publicKey);\n const rHat = [];\n for (let i = 0; i < K; i++) rHat.push(crystals.NTT.encode(sampleCBD(PRF, seed, i, ETA1)));\n const x = XOF(rho);\n const tmp2 = new Uint16Array(N);\n const u = [];\n for (let i = 0; i < K; i++) {\n const e1 = sampleCBD(PRF, seed, K + i, ETA2);\n const tmp = new Uint16Array(N);\n for (let j = 0; j < K; j++) {\n const aij = SampleNTT(x.get(i, j)); // A[j][i], inplace transpose access\n polyAdd(tmp, MultiplyNTTs(aij, rHat[j])); // t += aij * rHat[j]\n }\n polyAdd(e1, crystals.NTT.decode(tmp)); // e1 += tmp\n u.push(e1);\n polyAdd(tmp2, MultiplyNTTs(tHat[i], rHat[i])); // t2 += tHat[i] * rHat[i]\n cleanBytes(tmp);\n }\n x.clean();\n const e2 = sampleCBD(PRF, seed, 2 * K, ETA2);\n polyAdd(e2, crystals.NTT.decode(tmp2)); // e2 += tmp2\n const v = poly1.decode(msg); // encode plaintext m into polynomial v\n polyAdd(v, e2); // v += e2\n cleanBytes(tHat, rHat, tmp2, e2);\n return cipherCoder.encode([u, v]) as TRet<Uint8Array>;\n },\n decrypt: (cipherText: TArg<Uint8Array>, privateKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n const [u, v] = cipherCoder.decode(cipherText);\n const sk = secretCoder.decode(privateKey); // s ← ByteDecode_12(dkPKE)\n const tmp = new Uint16Array(N);\n // tmp += sk[i] * u[i]\n for (let i = 0; i < K; i++) polyAdd(tmp, MultiplyNTTs(sk[i], crystals.NTT.encode(u[i])));\n polySub(v, crystals.NTT.decode(tmp)); // w = v' - tmp\n cleanBytes(tmp, sk, u);\n return poly1.encode(v) as TRet<Uint8Array>;\n },\n };\n};\n\n/**\n * Public ML-KEM wrapper over the internal K-PKE subroutine.\n * `keygen(seed)` and `encapsulate(publicKey, msg)` are deterministic/test-oriented hooks that map\n * more directly to Algorithms 16-17 than to the pure no-input / random-internal Algorithms 19-20.\n * decapsulate() tries to follow the Algorithms 18/21 implicit-reject structure as closely as\n * practical here by re-encrypting, comparing ciphertexts, returning `Khat` on match or `Kbar` on\n * mismatch, and zeroizing the non-returned shared-secret candidate; JS/JIT still provides no\n * constant-time guarantees for that path.\n */\nfunction createKyber(opts: TArg<KyberOpts>): TRet<KEM> {\n const rawOpts = opts as KyberOpts;\n const KPKE = genKPKE(rawOpts);\n const { HASH256, HASH512, KDF } = rawOpts;\n const { secretCoder: KPKESecretCoder, lengths } = KPKE;\n const secretCoder = splitCoder('secretKey', lengths.secretKey, lengths.publicKey, 32, 32);\n const msgLen = 32;\n const seedLen = 64;\n const kemLengths = Object.freeze({\n ...lengths,\n seed: 64,\n msg: msgLen,\n msgRand: msgLen,\n secretKey: secretCoder.bytesLen,\n });\n return Object.freeze({\n info: Object.freeze({ type: 'ml-kem' }),\n lengths: kemLengths,\n keygen: (seed: TArg<Uint8Array> = randomBytes(seedLen)) => {\n abytes(seed, seedLen, 'seed');\n const { publicKey, secretKey: sk } = KPKE.keygen(seed.subarray(0, 32));\n const publicKeyHash = HASH256(publicKey);\n // (dkPKE||ek||H(ek)||z)\n const secretKey = secretCoder.encode([sk, publicKey, publicKeyHash, seed.subarray(32)]);\n cleanBytes(sk, publicKeyHash);\n return {\n publicKey: publicKey as TRet<Uint8Array>,\n secretKey: secretKey as TRet<Uint8Array>,\n };\n },\n getPublicKey: (secretKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n const [_sk, publicKey, _publicKeyHash, _z] = secretCoder.decode(secretKey);\n return Uint8Array.from(publicKey) as TRet<Uint8Array>;\n },\n encapsulate: (publicKey: TArg<Uint8Array>, msg: TArg<Uint8Array> = randomBytes(msgLen)) => {\n abytes(publicKey, lengths.publicKey, 'publicKey');\n abytes(msg, msgLen, 'message');\n\n // FIPS-203 includes additional verification check for modulus\n const eke = publicKey.subarray(0, 384 * opts.K);\n // Copy because of inplace encoding\n const ek = KPKESecretCoder.encode(KPKESecretCoder.decode(copyBytes(eke)));\n // (Modulus check.) Perform the computation ek ← ByteEncode12(ByteDecode12(eke)).\n // If ek = ̸ eke, the input is invalid. (See Section 4.2.1.)\n if (!equalBytes(ek, eke)) {\n cleanBytes(ek);\n throw new Error('ML-KEM.encapsulate: wrong publicKey modulus');\n }\n cleanBytes(ek);\n // derive randomness\n const kr = HASH512.create().update(msg).update(HASH256(publicKey)).digest();\n const cipherText = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));\n cleanBytes(kr.subarray(32));\n return {\n cipherText: cipherText as TRet<Uint8Array>,\n sharedSecret: kr.subarray(0, 32) as TRet<Uint8Array>,\n };\n },\n decapsulate: (cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>): TRet<Uint8Array> => {\n abytes(secretKey, secretCoder.bytesLen, 'secretKey'); // 768*k + 96\n abytes(cipherText, lengths.cipherText, 'cipherText'); // 32(du*k + dv)\n // test ← H(dk[384𝑘 ∶ 768𝑘 + 32])) .\n const k768 = secretCoder.bytesLen - 96;\n const start = k768 + 32;\n const test = HASH256(secretKey.subarray(k768 / 2, start));\n // If test ≠ dk[768𝑘 + 32 ∶ 768𝑘 + 64], then input checking has failed.\n if (!equalBytes(test, secretKey.subarray(start, start + 32)))\n throw new Error('invalid secretKey: hash check failed');\n const [sk, publicKey, publicKeyHash, z] = secretCoder.decode(secretKey);\n const msg = KPKE.decrypt(cipherText, sk);\n // derive randomness, Khat, rHat = G(mHat || h)\n const kr = HASH512.create().update(msg).update(publicKeyHash).digest();\n const Khat = kr.subarray(0, 32);\n // re-encrypt using the derived randomness\n const cipherText2 = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));\n // if ciphertexts do not match, “implicitly reject”\n const isValid = equalBytes(cipherText, cipherText2);\n const Kbar = KDF.create({ dkLen: 32 }).update(z).update(cipherText).digest();\n cleanBytes(msg, cipherText2, !isValid ? Khat : Kbar);\n return (isValid ? Khat : Kbar) as TRet<Uint8Array>;\n },\n });\n}\n\n// FIPS 203's PRF_eta binding: current callers use only 32-byte keys, one-byte nonces,\n// and dkLen values {128, 192}; out-of-range nonce numbers still wrap modulo 256 here.\nfunction shakePRF(dkLen: number, key: TArg<Uint8Array>, nonce: number): TRet<Uint8Array> {\n return shake256\n .create({ dkLen })\n .update(key)\n .update(new Uint8Array([nonce]))\n .digest() as TRet<Uint8Array>;\n}\n\n// Fixed ML-KEM hash/XOF bindings. `KDF` here is the spec's fixed 32-byte `J` call,\n// and swapping any field changes the scheme rather than tuning an internal dependency.\nconst opts = /* @__PURE__ */ (() => ({\n HASH256: sha3_256,\n HASH512: sha3_512,\n KDF: shake256,\n XOF: XOF128,\n PRF: shakePRF,\n}))();\n// Parameter-set instantiation step for the spec's \"ML-KEM-x\" names; current correctness relies\n// on the internal PARAMS rows rather than local validation of arbitrary KEMParam objects.\nconst mk = (params: KEMParam) =>\n createKyber({\n ...opts,\n ...params,\n });\n\n/**\n * ML-KEM-512: Table 2 row `k=2, η1=3, η2=2, du=10, dv=4`; Table 3 sizes `800/1632/768/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem512: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[512]))();\n/**\n * ML-KEM-768: Table 2 row `k=3, η1=2, η2=2, du=10, dv=4`; Table 3 sizes `1184/2400/1088/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem768: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[768]))();\n/**\n * ML-KEM-1024: Table 2 row `k=4, η1=2, η2=2, du=11, dv=5`; Table 3 sizes `1568/3168/1568/32`.\n * The ASD lifecycle note here is external policy guidance, not a FIPS 203 requirement.\n */\nexport const ml_kem1024: TRet<KEM> = /* @__PURE__ */ (() => mk(PARAMS[1024]))();\n\n// NOTE: for tests only, don't use. This keeps the exact internal ML-KEM math surfaces available\n// without re-implementing them in separate test code.\nexport const __tests: any = /* @__PURE__ */ (() =>\n Object.freeze({\n Compress_d: (x: number, d: number) => {\n if (d < 1 || d > 11) throw new Error(`Compress_d: expected d in [1..11], got ${d}`);\n return compress(d).encode(x) & getMask(d);\n },\n Decompress_d: (y: number, d: number) => {\n if (d < 1 || d > 11) throw new Error(`Decompress_d: expected d in [1..11], got ${d}`);\n return compress(d).decode(y);\n },\n ByteEncode_d: (F: TArg<Uint16Array>, d: number) => {\n if (d < 1 || d > 12) throw new Error(`ByteEncode_d: expected d in [1..12], got ${d}`);\n return byteCoder(d).encode(F as TRet<Uint16Array>);\n },\n ByteDecode_d: (B: TArg<Uint8Array>, d: number) => {\n if (d < 1 || d > 12) throw new Error(`ByteDecode_d: expected d in [1..12], got ${d}`);\n return byteCoder(d).decode(B);\n },\n NTT: (f: TArg<Uint16Array>) => crystals.NTT.encode(Uint16Array.from(f)),\n NTT_inv: (fHat: TArg<Uint16Array>) => crystals.NTT.decode(Uint16Array.from(fHat)),\n MultiplyNTTs: (fHat: TArg<Uint16Array>, gHat: TArg<Uint16Array>) =>\n MultiplyNTTs(Uint16Array.from(fHat), Uint16Array.from(gHat)),\n SamplePolyCBD: (B: TArg<Uint8Array>, eta: number) => {\n abytes(B, 64 * eta, 'B');\n return sampleCBDBytes(B, eta);\n },\n SampleNTT: (B: TArg<Uint8Array>) => {\n abytes(B, 34, 'B');\n const xof = XOF128(B.subarray(0, 32));\n try {\n return SampleNTT(xof.get(B[32], B[33]));\n } finally {\n xof.clean();\n }\n },\n }))();\n","/**\n * Post-Quantum Hybrid Cryptography\n *\n * The current implementation is flawed and likely redundant. We should offer\n * a small, generic API to compose hybrid schemes instead of reimplementing\n * protocol-specific logic (SSH, GPG, etc.) with ad hoc encodings.\n *\n * 1. Core Issues\n * - sign/verify: implemented as two separate operations with different keys.\n * - EC getSharedSecret: could be refactored into a proper KEM.\n * - Multiple calls: keys, signatures, and shared secrets could be\n * concatenated to reduce the number of API invocations.\n * - Reinvention: most libraries add strange domain separations and\n * encodings instead of simple byte concatenation.\n *\n * 2. API Goals\n * - Provide primitives to build hybrids generically.\n * - Avoid embedding SSH- or GPG-specific formats in the core API.\n *\n * 3. Edge Cases\n * • Variable-length signatures:\n * - DER-encoded (Weierstrass curves).\n * - Falcon (unpadded).\n * - Concatenation works only if length is fixed; otherwise a length\n * prefix is required (but that breaks compatibility).\n *\n * • getSharedSecret:\n * - Default: non-KEM (authenticated ECDH).\n * - KEM conversion: generate a random SK to remove implicit auth.\n *\n * 4. Common Pitfalls\n * - Seed expansion:\n * • Expanding a small seed into multiple keys reduces entropy.\n * • API should allow identity mapping (no expansion).\n *\n * - Skipping full point encoding:\n * • Some omit the compression byte (parity) for WebCrypto compatibility.\n * • Better: hash the raw secret; coordinate output is already non-uniform.\n * • Some curves (e.g., X448) produce secrets that must be re-hashed to match\n * symmetric-key lengths.\n *\n * - Combiner inconsistencies:\n * • Different domain separations and encodings across libraries.\n * • Should live at the application layer, since key lengths vary.\n *\n * 5. Protocol Examples\n * - SSH:\n * • Concatenate keys.\n * • Combiner: SHA-512.\n *\n * - GPG:\n * • Concatenate keys.\n * • Combiner:\n * SHA3-256(kemShare || ecdhShare || ciphertext || pubKey || algId || domSep || len(domSep))\n *\n * - TLS:\n * • Transcript-based derivation (HKDF).\n *\n * 6. Relevant Specs & Implementations\n * - IETF Hybrid KEM drafts:\n * • draft-irtf-cfrg-hybrid-kems\n * • draft-connolly-cfrg-xwing-kem\n * • draft-westerbaan-tls-xyber768d00\n *\n * - PQC Libraries:\n * • superdilithium (cyph/pqcrypto.js) – low adoption.\n * • hybrid-pqc (DogeProtocol, quantumcoinproject) – complex encodings.\n *\n * 7. Signatures\n * - Ed25519: fixed-size, easy to support.\n * - Variable-size: introduces custom format requirements; best left to\n * higher-level code.\n *\n * @module\n */\n/*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) */\nimport { type EdDSA } from '@noble/curves/abstract/edwards.js';\nimport { type MontgomeryECDH } from '@noble/curves/abstract/montgomery.js';\nimport { type ECDSA } from '@noble/curves/abstract/weierstrass.js';\nimport { x25519 } from '@noble/curves/ed25519.js';\nimport { p256, p384 } from '@noble/curves/nist.js';\nimport {\n asciiToBytes,\n bytesToNumberBE,\n bytesToNumberLE,\n concatBytes,\n numberToBytesBE,\n} from '@noble/curves/utils.js';\nimport { expand, extract } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { sha3_256, shake256 } from '@noble/hashes/sha3.js';\nimport { abytes, ahash, anumber, type CHash, type CHashXOF } from '@noble/hashes/utils.js';\nimport { ml_kem1024, ml_kem768 } from './ml-kem.ts';\nimport {\n cleanBytes,\n copyBytes,\n randomBytes,\n splitCoder,\n validateSigOpts,\n validateVerOpts,\n type CryptoKeys,\n type KEM,\n type Signer,\n type TArg,\n type TRet,\n} from './utils.ts';\n\ntype CurveAll = ECDSA | EdDSA | MontgomeryECDH;\ntype CurveECDH = ECDSA | MontgomeryECDH;\ntype CurveSign = ECDSA | EdDSA;\n\n// Can re-use if decide to signatures support, on other hand getSecretKey is specific and ugly\nfunction ecKeygen(curve: CurveAll, allowZeroKey: boolean = false) {\n const lengths = curve.lengths;\n let keygen = curve.keygen;\n if (allowZeroKey) {\n // Only the ECDSA/Weierstrass branch uses raw scalar-byte secret keys here. Edwards seeds are\n // hashed/pruned and Montgomery keys are clamped byte strings, so forcing Point.Fn semantics on\n // those curves would change key construction instead of just relaxing scalar range handling.\n if (!('getSharedSecret' in curve && 'sign' in curve && 'verify' in curve))\n throw new Error('allowZeroKey requires a Weierstrass curve');\n // This legacy flag is really \"skip the +1 shift\" for vector matching, not \"accept scalar 0\".\n // It swaps seeded Weierstrass keygen from reduction into [1, ORDER) to direct reduction into\n // [0, ORDER), which preserves exact reduced bytes but still leaves scalar 0 invalid.\n // This is ugly, but we need to return exact results here.\n const wCurve = curve as ECDSA;\n const Fn = wCurve.Point.Fn;\n // Unlike noble-curves' seeded Weierstrass keygen, this path removes the post-reduction +1.\n // That is enough to match exact reduced-vector bytes, but an all-zero seed still reduces to\n // scalar 0 here and getPublicKey(secretKey) throws instead of \"allowing zero\".\n keygen = (seed: TArg<Uint8Array> = randomBytes(lengths.seed)) => {\n abytes(seed, lengths.seed!, 'seed');\n const seedScalar = Fn.isLE ? bytesToNumberLE(seed) : bytesToNumberBE(seed);\n // Reduce directly into [0, ORDER); scalar 0 still stays invalid.\n const secretKey = Fn.toBytes(Fn.create(seedScalar));\n return {\n secretKey: secretKey as TRet<Uint8Array>,\n publicKey: curve.getPublicKey(secretKey) as TRet<Uint8Array>,\n };\n };\n }\n return {\n lengths: { secretKey: lengths.secretKey, publicKey: lengths.publicKey, seed: lengths.seed },\n keygen: (seed?: TArg<Uint8Array>) =>\n keygen(seed) as TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }>,\n getPublicKey: (secretKey: TArg<Uint8Array>) =>\n curve.getPublicKey(secretKey) as TRet<Uint8Array>,\n };\n}\n\n/**\n * Wraps an ECDH-capable curve as a KEM.\n * Shared secrets stay in the wrapped curve's raw ECDH byte format with no built-in KDF.\n * On SEC 1 / Weierstrass curves, that means the compressed shared-point body without the\n * 1-byte `0x02` / `0x03` prefix.\n * The X25519 path also leaves RFC 7748's optional all-zero shared-secret check to callers.\n * @param curve - Curve with `getSharedSecret`.\n * @param allowZeroKey - Legacy vector-matching toggle for Weierstrass keygen.\n * On Weierstrass curves this removes the usual post-reduction `+1` shift, changing seeded scalar\n * reduction from `[1, ORDER)` to direct reduction into `[0, ORDER)`. It does not make scalar zero\n * valid: an all-zero seed still derives scalar `0` and throws in `curve.getPublicKey(...)`.\n * Only supported on Weierstrass/ECDSA curves.\n * @returns KEM wrapper over the curve.\n * @throws If the curve does not expose `getSharedSecret`. {@link Error}\n * @example\n * Wrap an ECDH-capable curve as a generic KEM.\n * ```ts\n * import { x25519 } from '@noble/curves/ed25519.js';\n * import { ecdhKem } from '@noble/post-quantum/hybrid.js';\n * const kem = ecdhKem(x25519);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function ecdhKem(curve: CurveECDH, allowZeroKey: boolean = false): TRet<KEM> {\n const kg = ecKeygen(curve, allowZeroKey);\n if (!curve.getSharedSecret) throw new Error('wrong curve'); // ed25519 doesn't have one!\n return {\n lengths: { ...kg.lengths, msg: kg.lengths.seed, cipherText: kg.lengths.publicKey },\n keygen: kg.keygen,\n getPublicKey: kg.getPublicKey,\n encapsulate(\n publicKey: TArg<Uint8Array>,\n rand: TArg<Uint8Array> = randomBytes(curve.lengths.seed)\n ) {\n // Some curve.keygen(seed) paths reuse the provided seed buffer as secretKey; detach caller\n // randomness first so cleanBytes() only wipes wrapper-owned material.\n const seed = copyBytes(rand);\n let ek: Uint8Array | undefined = undefined;\n try {\n ek = this.keygen(seed).secretKey;\n const sharedSecret = this.decapsulate(publicKey, ek);\n const cipherText = curve.getPublicKey(ek) as TRet<Uint8Array>;\n return { sharedSecret, cipherText };\n } finally {\n // Invalid peer public keys can make decapsulation throw; wipe both the detached seed and\n // derived ephemeral secret key even when encapsulation aborts before returning.\n cleanBytes(seed);\n if (ek) cleanBytes(ek);\n }\n },\n decapsulate(cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) {\n const res = curve.getSharedSecret(secretKey, cipherText);\n return (curve.lengths.publicKeyHasPrefix ? res.subarray(1) : res) as TRet<Uint8Array>;\n },\n };\n}\n\n/**\n * Wraps a curve signer as a generic `Signer`.\n * Signatures stay in the wrapped curve's native byte encoding.\n * This wrapper does not normalize or document which per-curve signing options are meaningful.\n * @param curve - Curve with `sign` and `verify`.\n * @param allowZeroKey - Legacy vector-matching toggle for Weierstrass keygen.\n * On Weierstrass curves this removes the usual post-reduction `+1` shift, changing seeded scalar\n * reduction from `[1, ORDER)` to direct reduction into `[0, ORDER)`. It does not make scalar zero\n * valid: an all-zero seed still derives scalar `0` and throws in `curve.getPublicKey(...)`.\n * Only supported on Weierstrass/ECDSA curves.\n * @returns Signer wrapper over the curve.\n * @throws If the curve does not expose `sign` and `verify`. {@link Error}\n * @example\n * Wrap a curve signer as a generic signer.\n * ```ts\n * import { ed25519 } from '@noble/curves/ed25519.js';\n * import { ecSigner } from '@noble/post-quantum/hybrid.js';\n * const signer = ecSigner(ed25519);\n * const sigLen = signer.lengths.signature;\n * ```\n */\nexport function ecSigner(curve: CurveSign, allowZeroKey: boolean = false): TRet<Signer> {\n const kg = ecKeygen(curve, allowZeroKey);\n if (!curve.sign || !curve.verify) throw new Error('wrong curve'); // ed25519 doesn't have one!\n return {\n lengths: { ...kg.lengths, signature: curve.lengths.signature, signRand: 0 },\n keygen: kg.keygen,\n getPublicKey: kg.getPublicKey,\n sign: (message, secretKey, opts = {}) => {\n validateSigOpts(opts);\n // This generic wrapper intentionally keeps the Signer contract to message + key only.\n // Backend-specific knobs like ECDSA extraEntropy or Ed25519ctx context cannot be forwarded\n // uniformly through combineSigners(), so callers that need them must use the curve directly.\n if (opts.extraEntropy !== undefined)\n throw new Error(\n 'ecSigner does not support extraEntropy; use the underlying curve directly'\n );\n if (opts.context !== undefined)\n throw new Error('ecSigner does not support context; use the underlying curve directly');\n return curve.sign(message, secretKey) as TRet<Uint8Array>;\n },\n /** Verify one wrapped curve signature.\n * Returns the wrapped curve's `verify()` result for well-formed inputs. Throws on unsupported\n * generic opts and lets wrapped-curve malformed-input errors escape unchanged.\n */\n verify: (signature, message, publicKey, opts = {}) => {\n validateVerOpts(opts);\n if (opts.context !== undefined)\n throw new Error('ecSigner does not support context; use the underlying curve directly');\n return curve.verify(signature, message, publicKey);\n },\n };\n}\n\nfunction splitLengths<K extends string, T extends { lengths: Partial<Record<K, number>> }>(\n lst: T[],\n name: K\n) {\n // Preserve caller order exactly; raw numeric fields still decode as splitCoder() subarray views.\n return splitCoder(\n name,\n ...lst.map((i) => {\n if (typeof i.lengths[name] !== 'number') throw new Error('wrong length: ' + name);\n return i.lengths[name];\n })\n );\n}\n\n/** Seed-expansion callback used by the hybrid combiners. */\nexport type ExpandSeed = (seed: TArg<Uint8Array>, len: number) => TRet<Uint8Array>;\ntype XOF = CHashXOF<any, { dkLen: number }>;\n\n// It is XOF for most cases, but can be more complex!\n/**\n * Adapts an XOF into an `ExpandSeed` callback.\n * The returned callback interprets its second argument as an output byte length passed as `dkLen`.\n * @param xof - Extendable-output hash function.\n * @returns Seed expander using `dkLen`.\n * @example\n * Adapt an XOF into a seed expander.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * const expandSeed = expandSeedXof(shake256);\n * const seed = expandSeed(new Uint8Array([1]), 4);\n * ```\n */\nexport function expandSeedXof(xof: TArg<XOF>): TRet<ExpandSeed> {\n // Forward the caller seed directly: XOFs are expected to treat inputs as read-only, and this\n // adapter only translates the requested byte length into the hash API's `dkLen` option.\n return ((seed: TArg<Uint8Array>, seedLen: number): TRet<Uint8Array> =>\n (xof as XOF)(seed, { dkLen: seedLen }) as TRet<Uint8Array>) as TRet<ExpandSeed>;\n}\n\n/** Combines public keys, ciphertexts, and shared secrets into one shared secret. */\nexport type Combiner = (\n publicKeys: TArg<Uint8Array[]>,\n cipherTexts: TArg<Uint8Array[]>,\n sharedSecrets: TArg<Uint8Array[]>\n) => TRet<Uint8Array>;\n\nfunction combineKeys(\n realSeedLen: number | undefined, // how much bytes expandSeed expects\n expandSeed_: TArg<ExpandSeed>,\n ...ck_: TArg<CryptoKeys[]>\n) {\n const expandSeed = expandSeed_ as ExpandSeed;\n const ck = ck_ as CryptoKeys[];\n const seedCoder = splitLengths(ck, 'seed');\n const pkCoder = splitLengths(ck, 'publicKey');\n // Allows to use identity functions for combiner/expandSeed\n if (realSeedLen === undefined) realSeedLen = seedCoder.bytesLen;\n anumber(realSeedLen);\n function expandDecapsulationKey(seed: TArg<Uint8Array>): TRet<{\n secretKey: Uint8Array[];\n publicKey: Uint8Array[];\n }> {\n abytes(seed, realSeedLen!);\n const expandedRaw = expandSeed(seed, seedCoder.bytesLen);\n // Identity/subarray expanders can hand back caller-owned seed storage. Detach those outputs so\n // later cleanup can wipe the expanded schedule without mutating the caller's root seed bytes.\n const expandedSeed = expandedRaw.buffer === seed.buffer ? copyBytes(expandedRaw) : expandedRaw;\n const expanded: Uint8Array[] = [];\n const keySecret: Uint8Array[] = [];\n const secretKey: Uint8Array[] = [];\n const publicKey: Uint8Array[] = [];\n let ok = false;\n try {\n // seedCoder.decode() returns zero-copy slices into expandedSeed and can throw before child\n // keygen() runs, so keep the raw expanded buffer separate and copy each child seed before any\n // later cleanup wipes the shared backing bytes.\n for (const part of seedCoder.decode(expandedSeed)) expanded.push(copyBytes(part));\n for (let i = 0; i < ck.length; i++) {\n const keys = ck[i].keygen(expanded[i]);\n keySecret.push(keys.secretKey);\n secretKey.push(copyBytes(keys.secretKey));\n publicKey.push(keys.publicKey);\n }\n ok = true;\n return { secretKey, publicKey } as TRet<{\n secretKey: Uint8Array[];\n publicKey: Uint8Array[];\n }>;\n } finally {\n // Child keygen() can throw after deriving only a prefix of the composite key schedule. Keep\n // the exported copies on success, but wipe all temporary and partially built secret material\n // on either path so failures do not strand derived child seeds in memory.\n cleanBytes(expandedSeed, expanded, keySecret);\n if (!ok) cleanBytes(secretKey);\n }\n }\n return {\n info: { lengths: { seed: realSeedLen, publicKey: pkCoder.bytesLen, secretKey: realSeedLen } },\n getPublicKey(secretKey: TArg<Uint8Array>) {\n // Composite secret keys are root seeds, so public-key derivation reruns key expansion from\n // that seed instead of decoding a packed child-secret-key structure.\n return this.keygen(secretKey).publicKey as TRet<Uint8Array>;\n },\n keygen(seed: TArg<Uint8Array> = randomBytes(realSeedLen)) {\n const { publicKey: pk, secretKey } = expandDecapsulationKey(seed);\n try {\n const publicKey = pkCoder.encode(pk) as TRet<Uint8Array>;\n return { secretKey: seed as TRet<Uint8Array>, publicKey };\n } finally {\n cleanBytes(pk);\n // The exported secretKey is the caller/root seed itself; child secret keys are internal\n // expansion outputs that are cleaned whether encoding succeeds or throws.\n cleanBytes(secretKey);\n }\n },\n expandDecapsulationKey,\n realSeedLen,\n };\n}\n\n// This generic function that combines multiple KEMs into single one\n/**\n * Combines multiple KEMs into one composite KEM.\n * @param realSeedLen - Input seed length expected by `expandSeed`.\n * @param realMsgLen - Shared-secret length returned by `combiner`.\n * @param expandSeed - Seed expander used to derive per-KEM seeds.\n * @param combiner - Combines the per-KEM outputs into one shared secret.\n * @param kems - KEM implementations to combine.\n * @returns Composite KEM.\n * @example\n * Combine multiple KEMs into one composite KEM.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { combineKEMS, expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * const hybrid = combineKEMS(\n * 32,\n * 32,\n * expandSeedXof(shake256),\n * (_pk, _ct, sharedSecrets) => sharedSecrets[0],\n * ml_kem768,\n * ml_kem768\n * );\n * const { publicKey } = hybrid.keygen();\n * ```\n */\nexport function combineKEMS(\n realSeedLen: number | undefined, // how much bytes expandSeed expects\n realMsgLen: number | undefined, // how much bytes combiner returns\n expandSeed: TArg<ExpandSeed>,\n combiner: TArg<Combiner>,\n ...kems: TArg<KEM[]>\n): TRet<KEM> {\n const rawCombiner = combiner as Combiner;\n const rawKems = kems as KEM[];\n const keys = combineKeys(realSeedLen, expandSeed, ...rawKems);\n const ctCoder = splitLengths(rawKems, 'cipherText');\n const pkCoder = splitLengths(rawKems, 'publicKey');\n const msgCoder = splitLengths(rawKems, 'msg');\n if (realMsgLen === undefined) realMsgLen = msgCoder.bytesLen;\n anumber(realMsgLen);\n const lengths = Object.freeze({\n ...keys.info.lengths,\n msg: realMsgLen,\n msgRand: msgCoder.bytesLen,\n cipherText: ctCoder.bytesLen,\n });\n return Object.freeze({\n lengths,\n getPublicKey: keys.getPublicKey,\n keygen: keys.keygen,\n encapsulate(\n pk: TArg<Uint8Array>,\n randomness: TArg<Uint8Array> = randomBytes(msgCoder.bytesLen)\n ) {\n const pks = pkCoder.decode(pk);\n const rand = msgCoder.decode(randomness);\n const sharedSecret: Uint8Array[] = [];\n const cipherText: Uint8Array[] = [];\n try {\n for (let i = 0; i < rawKems.length; i++) {\n const enc = rawKems[i].encapsulate(pks[i], rand[i]);\n sharedSecret.push(enc.sharedSecret);\n cipherText.push(enc.cipherText);\n }\n return {\n // Detach the combiner result before cleanup: a caller-provided combiner may alias one of\n // the child sharedSecret buffers, and those child buffers are zeroized immediately below.\n sharedSecret: copyBytes(rawCombiner(pks, cipherText, sharedSecret)),\n cipherText: ctCoder.encode(cipherText) as TRet<Uint8Array>,\n };\n } finally {\n // Child encapsulation or combiner failures can happen after some components already\n // returned secret material; zeroize whatever was produced before propagating the error.\n cleanBytes(sharedSecret, cipherText);\n }\n },\n decapsulate(ct: TArg<Uint8Array>, seed: TArg<Uint8Array>) {\n const cts = ctCoder.decode(ct);\n const { publicKey, secretKey } = keys.expandDecapsulationKey(seed);\n const sharedSecret = rawKems.map((i, j) => i.decapsulate(cts[j], secretKey[j]));\n try {\n // Detach the decapsulation result before cleanup: the combiner may hand back one of the\n // child shared-secret buffers, and those temporary buffers are zeroized below.\n return copyBytes(rawCombiner(publicKey, cts, sharedSecret));\n } finally {\n // Decapsulation only needs the expanded child secret keys and child shared secrets for this\n // call; keep the caller/root seed intact, but wipe all derived material even on errors.\n cleanBytes(secretKey, sharedSecret);\n }\n },\n });\n}\n// There is no specs for this, but can be useful\n// realSeedLen: how much bytes expandSeed expects.\n/**\n * Combines multiple signers into one composite signer.\n * @param realSeedLen - Input seed length expected by `expandSeed`.\n * @param expandSeed - Seed expander used to derive per-signer seeds.\n * @param signers - Signers to combine.\n * @returns Composite signer.\n * @example\n * Combine multiple signers into one composite signer.\n * ```ts\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { combineSigners, expandSeedXof } from '@noble/post-quantum/hybrid.js';\n * import { ml_dsa44 } from '@noble/post-quantum/ml-dsa.js';\n * const hybrid = combineSigners(32, expandSeedXof(shake256), ml_dsa44, ml_dsa44);\n * const { publicKey } = hybrid.keygen();\n * ```\n */\nexport function combineSigners(\n realSeedLen: number | undefined,\n expandSeed: TArg<ExpandSeed>,\n ...signers: TArg<Signer[]>\n): TRet<Signer> {\n const rawSigners = signers as Signer[];\n const keys = combineKeys(realSeedLen, expandSeed, ...rawSigners);\n const sigCoder = splitLengths(rawSigners, 'signature');\n const pkCoder = splitLengths(rawSigners, 'publicKey');\n return {\n lengths: { ...keys.info.lengths, signature: sigCoder.bytesLen, signRand: 0 },\n getPublicKey: keys.getPublicKey,\n keygen: keys.keygen,\n sign(message, seed, opts = {}) {\n validateSigOpts(opts);\n // This generic wrapper intentionally keeps the composite signer contract to message + root\n // seed only. Per-signer opts like context or extraEntropy cannot be preserved uniformly\n // across mixed backends, so callers that need them must use the underlying signer directly.\n if (opts.extraEntropy !== undefined)\n throw new Error(\n 'combineSigners does not support extraEntropy; use the underlying signer directly'\n );\n if (opts.context !== undefined)\n throw new Error(\n 'combineSigners does not support context; use the underlying signer directly'\n );\n const { secretKey } = keys.expandDecapsulationKey(seed);\n try {\n const sigs = rawSigners.map((i, j) => i.sign(message, secretKey[j]));\n return sigCoder.encode(sigs) as TRet<Uint8Array>;\n } finally {\n // Composite secret keys are root seeds; the per-signer child secret keys are temporary\n // expansion outputs and must not stay live after the combined signature is produced.\n cleanBytes(secretKey);\n }\n },\n /** Verify one combined signature.\n * Returns `false` when the aggregate signature/publicKey decode succeeds but any child verify\n * check fails. Throws on unsupported generic opts or malformed aggregate encodings.\n */\n verify: (signature, message, publicKey, opts = {}) => {\n validateVerOpts(opts);\n if (opts.context !== undefined)\n throw new Error(\n 'combineSigners does not support context; use the underlying signer directly'\n );\n const pks = pkCoder.decode(publicKey);\n const sigs = sigCoder.decode(signature);\n for (let i = 0; i < rawSigners.length; i++) {\n if (!rawSigners[i].verify(sigs[i], message, pks[i])) return false;\n }\n return true;\n },\n };\n}\n\n/**\n * Builds a QSF hybrid KEM preset from a PQ KEM and an elliptic-curve KEM.\n * The combined shared-secret length follows `kdf.outputLen`; the built-in presets use 32-byte\n * SHA3-256 output, while custom `kdf` choices inherit their own digest size.\n * Its combiner hashes `ss0 || ss1 || ct1 || pk1 || label`, not the full\n * `(c1, c2, ek1, ek2)` example input shape from SP 800-227 equation (15).\n * Labels are encoded with `asciiToBytes()`, so non-ASCII labels are rejected.\n * @param label - Domain-separation label.\n * @param pqc - Post-quantum KEM.\n * @param curveKEM - Classical curve KEM.\n * @param xof - XOF used for seed expansion.\n * @param kdf - Hash used for the final combiner.\n * @returns Hybrid KEM.\n * @example\n * Build a QSF hybrid KEM preset from a PQ KEM and an elliptic-curve KEM.\n * ```ts\n * import { p256 } from '@noble/curves/nist.js';\n * import { sha3_256, shake256 } from '@noble/hashes/sha3.js';\n * import { QSF, ecdhKem } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * const kem = QSF('example', ml_kem768, ecdhKem(p256, true), shake256, sha3_256);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function QSF(\n label: string,\n pqc: TArg<KEM>,\n curveKEM: TArg<KEM>,\n xof: TArg<XOF>,\n kdf: CHash\n): TRet<KEM> {\n ahash(xof);\n ahash(kdf);\n return combineKEMS(\n 32,\n kdf.outputLen,\n expandSeedXof(xof),\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n kdf(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes(label))),\n pqc,\n curveKEM\n );\n}\n\n/** QSF preset combining ML-KEM-768 with P-256. */\nexport const QSF_ml_kem768_p256: TRet<KEM> = /* @__PURE__ */ (() =>\n QSF(\n 'QSF-KEM(ML-KEM-768,P-256)-XOF(SHAKE256)-KDF(SHA3-256)',\n ml_kem768,\n ecdhKem(p256, true),\n shake256,\n sha3_256\n ))();\n/** QSF preset combining ML-KEM-1024 with P-384. */\nexport const QSF_ml_kem1024_p384: TRet<KEM> = /* @__PURE__ */ (() =>\n QSF(\n 'QSF-KEM(ML-KEM-1024,P-384)-XOF(SHAKE256)-KDF(SHA3-256)',\n ml_kem1024,\n ecdhKem(p384, true),\n shake256,\n sha3_256\n ))();\n\n/**\n * Builds the \"KitchenSink\" hybrid KEM combiner.\n * The current builder always derives a fixed 32-byte output,\n * regardless of the hash's native output size.\n * Its HKDF extract step uses implicit zero salt with IKM\n * `hybrid_prk || ss0 || ss1 || ct0 || pk0 || ct1 || pk1 || label`.\n * Its HKDF expand step fixes `info` to `len || 'shared_secret' || ''`.\n * Labels are encoded with `asciiToBytes()`, so non-ASCII labels are rejected.\n * @param label - Domain-separation label.\n * @param pqc - Post-quantum KEM.\n * @param curveKEM - Classical curve KEM.\n * @param xof - XOF used for seed expansion.\n * @param hash - Hash used for HKDF extraction and expansion.\n * @returns Hybrid KEM.\n * @example\n * Build the \"KitchenSink\" hybrid KEM combiner.\n * ```ts\n * import { sha256 } from '@noble/hashes/sha2.js';\n * import { shake256 } from '@noble/hashes/sha3.js';\n * import { createKitchenSink, ecdhKem } from '@noble/post-quantum/hybrid.js';\n * import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n * import { x25519 } from '@noble/curves/ed25519.js';\n * const kem = createKitchenSink('example', ml_kem768, ecdhKem(x25519), shake256, sha256);\n * const publicKeyLen = kem.lengths.publicKey;\n * ```\n */\nexport function createKitchenSink(\n label: string,\n pqc: TArg<KEM>,\n curveKEM: TArg<KEM>,\n xof: TArg<XOF>,\n hash: CHash\n): TRet<KEM> {\n ahash(xof);\n ahash(hash);\n return combineKEMS(\n 32,\n 32,\n expandSeedXof(xof),\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) => {\n const preimage = concatBytes(ss[0], ss[1], ct[0], pk[0], ct[1], pk[1], asciiToBytes(label));\n const len = 32;\n const ikm = concatBytes(asciiToBytes('hybrid_prk'), preimage);\n const prk = extract(hash, ikm);\n const info = concatBytes(\n numberToBytesBE(len, 2),\n asciiToBytes('shared_secret'),\n asciiToBytes('')\n );\n const res = expand(hash, prk, info, len);\n cleanBytes(prk, info, ikm, preimage);\n return res;\n },\n pqc,\n curveKEM\n );\n}\n\n// Internal alias only: this stays exactly `ecdhKem(x25519)`\n// and inherits that wrapper's mutation/oracle behavior.\nconst x25519kem = /* @__PURE__ */ ecdhKem(x25519);\n/** KitchenSink preset combining ML-KEM-768 with X25519.\n * Caller randomness splits into 32 ML-KEM coins plus a 32-byte X25519 ephemeral-secret seed.\n */\nexport const KitchenSink_ml_kem768_x25519: TRet<KEM> = /* @__PURE__ */ (() =>\n createKitchenSink(\n 'KitchenSink-KEM(ML-KEM-768,X25519)-XOF(SHAKE256)-KDF(HKDF-SHA-256)',\n ml_kem768,\n x25519kem,\n shake256,\n sha256\n ))();\n\n// Always X25519 and ML-KEM - 768, no point to export\n/** X25519 + ML-KEM-768 hybrid preset.\n * Uses the hard-coded domain-separation label `\\\\.//^\\\\` and hashes only `ct1 || pk1`\n * from the X25519 side in addition to the two component shared secrets.\n */\nexport const ml_kem768_x25519: TRet<KEM> = /* @__PURE__ */ (() =>\n combineKEMS(\n 32,\n 32,\n expandSeedXof(shake256),\n // Awesome label, so much escaping hell in a single line.\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes('\\\\.//^\\\\'))),\n ml_kem768,\n x25519kem\n ))();\n\n/**\n * Internal SEC 1-style KEM wrapper for NIST curves.\n * `nseed` is only the rejection-sampling byte budget for deriving one nonzero scalar:\n * current presets use `128` bytes for P-256 and `48` bytes for P-384.\n * `decapsulate()` returns the uncompressed shared point body `x || y` without the `0x04`\n * prefix, not the SEC 1 `x_P`-only primitive output, because current hybrid combiners hash\n * both coordinates.\n */\nfunction nistCurveKem(curve: ECDSA, scalarLen: number, elemLen: number, nseed: number): TRet<KEM> {\n const Fn = curve.Point.Fn;\n if (!Fn) throw new Error('no Point.Fn');\n // Scan scalar-sized windows until one decodes to a nonzero scalar in `[1, n-1]`; if every\n // window is zero or out of range, fail instead of silently reducing modulo `n`.\n function rejectionSampling(seed: TArg<Uint8Array>): TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }> {\n let sk: bigint;\n for (let start = 0, end = scalarLen; ; start = end, end += scalarLen) {\n if (end > seed.length) throw new Error('rejection sampling failed');\n sk = Fn.fromBytes(seed.subarray(start, end), true);\n if (Fn.isValidNot0(sk)) break;\n }\n const secretKey = Fn.toBytes(Fn.create(sk));\n const publicKey = curve.getPublicKey(secretKey, false);\n return { secretKey, publicKey } as TRet<{\n secretKey: Uint8Array;\n publicKey: Uint8Array;\n }>;\n }\n\n return {\n lengths: {\n secretKey: scalarLen,\n publicKey: elemLen,\n seed: nseed,\n msg: nseed,\n cipherText: elemLen,\n },\n keygen(seed: TArg<Uint8Array> = randomBytes(nseed)) {\n abytes(seed, nseed, 'seed');\n return rejectionSampling(seed);\n },\n getPublicKey(secretKey: TArg<Uint8Array>) {\n return curve.getPublicKey(secretKey, false) as TRet<Uint8Array>;\n },\n encapsulate(publicKey: TArg<Uint8Array>, rand: TArg<Uint8Array> = randomBytes(nseed)) {\n abytes(rand, nseed, 'rand');\n let ek: Uint8Array | undefined = undefined;\n try {\n ek = rejectionSampling(rand).secretKey;\n const sharedSecret = this.decapsulate(publicKey, ek);\n const cipherText = curve.getPublicKey(ek, false) as TRet<Uint8Array>;\n return { sharedSecret, cipherText };\n } finally {\n // Rejection-sampled NIST-curve ephemeral secret keys are temporary encapsulation state and\n // must be wiped even if peer-key validation or shared-secret derivation throws.\n if (ek) cleanBytes(ek);\n }\n },\n decapsulate(cipherText: TArg<Uint8Array>, secretKey: TArg<Uint8Array>) {\n const full = curve.getSharedSecret(secretKey, cipherText);\n return full.subarray(1) as TRet<Uint8Array>;\n },\n };\n}\n\n/**\n * Internal ML-KEM + NIST-curve combiner.\n * `nseed` controls only the curve-side rejection-sampling budget; it is expanded from the\n * 32-byte root seed and is not itself part of the exported secret-key length.\n * The domain-separation `label` is used only in the final `sha3_256` combiner, not in\n * `shake256(seed, { dkLen: 64 + nseed })`,\n * and the combiner hashes `ss0 || ss1 || ct1 || pk1 || label`.\n */\nfunction concreteHybridKem(\n label: string,\n mlkem: TArg<KEM>,\n curve: ECDSA,\n nseed: number\n): TRet<KEM> {\n const { secretKey: scalarLen, publicKeyUncompressed: elemLen } = curve.lengths;\n if (!scalarLen || !elemLen) throw new Error('wrong curve');\n const curveKem = nistCurveKem(curve, scalarLen, elemLen, nseed);\n const mlkemSeedLen = 64;\n const totalSeedLen = mlkemSeedLen + nseed;\n\n return combineKEMS(\n 32,\n 32,\n (seed: TArg<Uint8Array>): TRet<Uint8Array> => {\n abytes(seed, 32);\n const expanded = shake256(seed, { dkLen: totalSeedLen });\n const mlkemSeed = expanded.subarray(0, mlkemSeedLen);\n const curveSeed = expanded.subarray(mlkemSeedLen, totalSeedLen);\n return concatBytes(mlkemSeed, curveSeed) as TRet<Uint8Array>;\n },\n (pk: TArg<Uint8Array[]>, ct: TArg<Uint8Array[]>, ss: TArg<Uint8Array[]>) =>\n sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes(label))),\n mlkem,\n curveKem\n );\n}\n\n/** P-256 + ML-KEM-768 hybrid preset. */\nexport const ml_kem768_p256: TRet<KEM> = /* @__PURE__ */ (() =>\n concreteHybridKem('MLKEM768-P256', ml_kem768, p256, 128))();\n\n/** P-384 + ML-KEM-1024 hybrid preset. */\nexport const ml_kem1024_p384: TRet<KEM> = /* @__PURE__ */ (() =>\n concreteHybridKem('MLKEM1024-P384', ml_kem1024, p384, 48))();\n\n// Legacy aliases\n/** Legacy alias for `ml_kem768_x25519`. */\nexport const XWing: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_x25519)();\n/** Legacy alias for `ml_kem768_x25519`. */\nexport const MLKEM768X25519: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_x25519)();\n/** Legacy alias for `ml_kem768_p256`. */\nexport const MLKEM768P256: TRet<KEM> = /* @__PURE__ */ (() => ml_kem768_p256)();\n/** Legacy alias for `ml_kem1024_p384`. */\nexport const MLKEM1024P384: TRet<KEM> = /* @__PURE__ */ (() => ml_kem1024_p384)();\n/** Legacy alias for `QSF_ml_kem768_p256`. */\nexport const QSFMLKEM768P256: TRet<KEM> = /* @__PURE__ */ (() => QSF_ml_kem768_p256)();\n/** Legacy alias for `QSF_ml_kem1024_p384`. */\nexport const QSFMLKEM1024P384: TRet<KEM> = /* @__PURE__ */ (() => QSF_ml_kem1024_p384)();\n/** Legacy alias for `KitchenSink_ml_kem768_x25519`. */\nexport const KitchenSinkMLKEM768X25519: TRet<KEM> = /* @__PURE__ */ (() =>\n KitchenSink_ml_kem768_x25519)();\n","import { hkdf } from '@noble/hashes/hkdf.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nexport interface HkdfSha256Opts {\n readonly ikm: Uint8Array;\n readonly salt: Uint8Array;\n readonly info: Uint8Array;\n readonly length: number;\n}\n\nexport function hkdfSha256(opts: HkdfSha256Opts): Uint8Array {\n return hkdf(sha256, opts.ikm, opts.salt, opts.info, opts.length);\n}\n","import { XWing } from '@noble/post-quantum/hybrid.js';\n\n// X-Wing (ML-KEM-768 + X25519) hybrid KEM per draft-connolly-cfrg-xwing-kem-10.\n// `XWing` is @noble/post-quantum's alias for `ml_kem768_x25519`. We expose it\n// through opts-object wrappers that pin the wire lengths and map noble's field\n// names onto the project's vocabulary.\n//\n// Unlike the bare X25519 KEM, there is no contributory-behaviour rejection to\n// translate: X-Wing combines the ML-KEM and X25519 shared secrets through a\n// SHA3-256 combiner that also binds the X25519 ephemeral and recipient public\n// keys, and ML-KEM's implicit rejection already yields a constant-work\n// pseudorandom secret on a malformed ciphertext. Decapsulation therefore never\n// throws on attacker-supplied wire data — a wrong shared secret is the correct,\n// indistinguishable failure mode, and callers MUST treat it as a non-match\n// rather than expecting an exception.\n\nexport const MLKEM768X25519_PUBLIC_KEY_LENGTH = 1216 as const;\nexport const MLKEM768X25519_ENC_LENGTH = 1120 as const;\nexport const MLKEM768X25519_SHARED_SECRET_LENGTH = 32 as const;\nexport const MLKEM768X25519_SEED_LENGTH = 32 as const;\nexport const MLKEM768X25519_ESEED_LENGTH = 64 as const;\n\nexport interface Mlkem768X25519KeyPair {\n // The 32-byte root seed IS the secret key: the ML-KEM coins and the X25519\n // scalar are re-expanded from it via SHAKE-256 at decapsulation. (Later X-Wing\n // drafts also define an optional expanded decapsulation-key form; we keep the\n // seed-only key, which the draft-10 Appendix C vectors still pin.)\n readonly secretSeed: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface Mlkem768X25519EncapsulateOpts {\n readonly publicKey: Uint8Array;\n // Optional 64-byte encapsulation randomness (msgRand). When supplied the\n // ciphertext and shared secret are fully deterministic; a 32-byte value is\n // rejected by noble, so we pin the length here too.\n readonly eseed?: Uint8Array;\n}\n\nexport interface Mlkem768X25519Encapsulation {\n readonly enc: Uint8Array;\n readonly ss: Uint8Array;\n}\n\nexport interface Mlkem768X25519DecapsulateOpts {\n readonly secretSeed: Uint8Array;\n readonly enc: Uint8Array;\n}\n\nexport function mlkem768x25519Keygen(seed: Uint8Array): Mlkem768X25519KeyPair {\n if (seed.length !== MLKEM768X25519_SEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 seed must be ${MLKEM768X25519_SEED_LENGTH} bytes, got ${seed.length}`,\n );\n }\n const { secretKey, publicKey } = XWing.keygen(seed);\n return { secretSeed: secretKey, publicKey };\n}\n\nexport function mlkem768x25519Encapsulate(\n opts: Mlkem768X25519EncapsulateOpts,\n): Mlkem768X25519Encapsulation {\n if (opts.publicKey.length !== MLKEM768X25519_PUBLIC_KEY_LENGTH) {\n throw new Error(\n `mlkem768x25519 public key must be ${MLKEM768X25519_PUBLIC_KEY_LENGTH} bytes, got ${opts.publicKey.length}`,\n );\n }\n if (opts.eseed !== undefined && opts.eseed.length !== MLKEM768X25519_ESEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 eseed must be ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${opts.eseed.length}`,\n );\n }\n const { cipherText, sharedSecret } = XWing.encapsulate(opts.publicKey, opts.eseed);\n return { enc: cipherText, ss: sharedSecret };\n}\n\nexport function mlkem768x25519Decapsulate(opts: Mlkem768X25519DecapsulateOpts): Uint8Array {\n // Pre-check both lengths before calling noble: decapsulation must perform a\n // constant amount of work for any caller-supplied ciphertext (implicit\n // rejection), which requires the inputs to be the exact expected sizes.\n if (opts.secretSeed.length !== MLKEM768X25519_SEED_LENGTH) {\n throw new Error(\n `mlkem768x25519 secret seed must be ${MLKEM768X25519_SEED_LENGTH} bytes, got ${opts.secretSeed.length}`,\n );\n }\n if (opts.enc.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new Error(\n `mlkem768x25519 enc must be ${MLKEM768X25519_ENC_LENGTH} bytes, got ${opts.enc.length}`,\n );\n }\n // noble's signature is decapsulate(cipherText, secretKey) — ciphertext first.\n return XWing.decapsulate(opts.enc, opts.secretSeed);\n}\n","import { x25519 } from '@noble/curves/ed25519.js';\n\n// RFC 7748 §6.1 contributory-behaviour rejection: a small-order (low-order)\n// Montgomery `u` coordinate makes the X25519 shared secret all-zero, which\n// @noble/curves refuses with `Error: invalid private or public key received`.\n// We rethrow that as a *typed* error so callers can distinguish a structurally\n// valid-but-malicious peer public key (a property of attacker-supplied wire\n// data — trial-decrypt MUST treat the slot as a non-match, not crash) from\n// genuine caller misuse such as a wrong-length key (which @noble raises as a\n// RangeError and which we deliberately let propagate untouched).\nexport class X25519LowOrderPointError extends Error {\n readonly code = 'X25519_LOW_ORDER_POINT' as const;\n constructor(options?: { cause?: unknown }) {\n super('x25519 ECDH rejected: peer public key is a small-order point', options);\n this.name = 'X25519LowOrderPointError';\n }\n}\n\n// @noble/curves v2 signals a small-order/all-zero shared secret with this exact\n// message. Matching on it (rather than the broad Error class) keeps unrelated\n// failures — e.g. a future internal assertion — surfacing as themselves.\nconst NOBLE_LOW_ORDER_MESSAGE = 'invalid private or public key received';\n\nexport interface X25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface X25519PublicKeyOpts {\n readonly secretKey: Uint8Array;\n}\n\nexport interface X25519EcdhOpts {\n readonly secretKey: Uint8Array;\n readonly theirPublicKey: Uint8Array;\n}\n\nexport function x25519Keygen(): X25519KeyPair {\n return x25519.keygen();\n}\n\nexport function x25519PublicKey(opts: X25519PublicKeyOpts): Uint8Array {\n return x25519.getPublicKey(opts.secretKey);\n}\n\nexport function x25519Ecdh(opts: X25519EcdhOpts): Uint8Array {\n try {\n return x25519.getSharedSecret(opts.secretKey, opts.theirPublicKey);\n } catch (e) {\n // Translate ONLY the contributory-check rejection into our typed error.\n // A wrong-length key throws a RangeError from @noble's length assertion;\n // that is caller misuse, not malicious wire data, so it must propagate.\n if (e instanceof Error && e.message === NOBLE_LOW_ORDER_MESSAGE) {\n throw new X25519LowOrderPointError({ cause: e });\n }\n throw e;\n }\n}\n","import * as ed from '@noble/ed25519';\nimport { sha512 } from '@noble/hashes/sha2.js';\n\ned.hashes.sha512 = sha512;\n\n// Ed25519 group order L (= 2^252 + 27742317777372353535851937790883648493).\nconst L = ed.Point.CURVE().n;\n\nexport interface SignEd25519Opts {\n readonly seed: Uint8Array;\n readonly message: Uint8Array;\n}\n\nexport interface VerifyEd25519Opts {\n readonly publicKey: Uint8Array;\n readonly message: Uint8Array;\n readonly signature: Uint8Array;\n}\n\nexport interface GetPublicKeyEd25519Opts {\n readonly seed: Uint8Array;\n}\n\nexport function signEd25519(opts: SignEd25519Opts): Uint8Array {\n return ed.sign(opts.message, opts.seed);\n}\n\n// Little-endian 32-byte scalar → bigint.\nfunction leBytesToBigInt(bytes: Uint8Array): bigint {\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) {\n value = (value << 8n) | BigInt(bytes[i]!);\n }\n return value;\n}\n\n// Strict (non-cofactored) Ed25519 verification per RFC 8032 §5.1.7, matching\n// libsodium/PyNaCl `crypto_sign_verify_detached` and ed25519-dalek\n// `verify_strict`. The cofactor-less check rejects every small-order /\n// torsion-component edge case in the C2SP/CCTV corpus, which noble's\n// `{ zip215: false }` mode does NOT (it remains cofactored: it checks\n// `[8]([S]B - [k]A - R) == 0`, accepting torsion components).\n//\n// The verification equation is the unscaled `[S]B == R + [k]A`, rewritten as\n// `[S]B - [k]A - R == identity`. We reject S >= L (non-canonical scalar) and\n// any small-order A or R up front, so a torsion component can never be smuggled\n// through the cofactor multiplication the cofactored variant performs.\nexport function verifyEd25519(opts: VerifyEd25519Opts): boolean {\n const { signature, message, publicKey } = opts;\n if (signature.length !== 64 || publicKey.length !== 32) return false;\n\n // S = LE(sig[32..64]); reject if not a canonical scalar (S >= L).\n const S = leBytesToBigInt(signature.subarray(32, 64));\n if (S >= L) return false;\n\n // Decode A (public key) and R (sig[0..32]) with the canonical (non-zip215)\n // point encoding; a non-canonical encoding throws and rejects.\n let A: ed.Point;\n let R: ed.Point;\n try {\n A = ed.Point.fromBytes(publicKey);\n R = ed.Point.fromBytes(signature.subarray(0, 32));\n } catch {\n return false;\n }\n\n // Reject small-order (cofactor-torsion) A or R: this is exactly the strictness\n // that distinguishes verify_strict from the cofactored check.\n if (A.isSmallOrder() || R.isSmallOrder()) return false;\n\n // k = SHA-512(R || A || M) reduced mod L.\n const k =\n leBytesToBigInt(ed.hash(concatBytes(signature.subarray(0, 32), publicKey, message))) % L;\n\n // Accept iff [S]B - [k]A - R == identity. `multiplyUnsafe` returns the\n // identity for a 0 scalar, but guard explicitly to avoid relying on that.\n const sB = S === 0n ? ed.Point.ZERO : ed.Point.BASE.multiplyUnsafe(S);\n const kA = k === 0n ? ed.Point.ZERO : A.multiplyUnsafe(k);\n return sB.subtract(kA).subtract(R).is0();\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += p.length;\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nexport function getPublicKeyEd25519(opts: GetPublicKeyEd25519Opts): Uint8Array {\n return ed.getPublicKey(opts.seed);\n}\n","export type SeedDeriveErrorCode = 'INVALID_SEED_LENGTH';\n\nexport class SeedDeriveError extends Error {\n readonly code: SeedDeriveErrorCode;\n\n constructor(code: SeedDeriveErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'SeedDeriveError';\n this.code = code;\n }\n}\n\nexport type SeedEncodingErrorCode =\n | 'INVALID_SEED_LENGTH'\n | 'SEED_STRING_MIXED_CASE'\n | 'SEED_STRING_BAD_CHECKSUM'\n | 'SEED_STRING_WRONG_HRP'\n | 'SEED_STRING_WRONG_LENGTH'\n | 'SEED_STRING_UNRECOGNIZED';\n\n// Raised by the identity-seed string codec (`encodeIdentitySeed` /\n// `parseIdentitySeed`). The codes are the cross-implementation contract: every\n// conforming implementation rejects the same malformed input with the same code.\nexport class SeedEncodingError extends Error {\n readonly code: SeedEncodingErrorCode;\n\n constructor(code: SeedEncodingErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'SeedEncodingError';\n this.code = code;\n }\n}\n","import { hkdfSha256 } from '../kdf/hkdf';\nimport { mlkem768x25519Keygen } from '../kem/mlkem768x25519';\nimport { x25519PublicKey } from '../kem/x25519';\nimport { getPublicKeyEd25519 } from '../sig/ed25519';\n\nimport { SeedDeriveError } from './errors';\n\n// HKDF info constants for the long-term identity keypairs.\n// These literal byte sequences are part of the on-wire protocol; every\n// conformant implementation MUST hash against these exact ASCII bytes (the\n// Python parity twin pins the identical labels).\nexport const INFO_ED25519: Uint8Array = new TextEncoder().encode('cardano-poe-ed25519-v1');\nexport const INFO_X25519: Uint8Array = new TextEncoder().encode('cardano-poe-x25519-v1');\nexport const INFO_MLKEM768X25519: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-mlkem768x25519-v1',\n);\n\nif (INFO_ED25519.length !== 22) {\n throw new Error('INFO_ED25519 byte-length invariant violated (expected 22)');\n}\nif (INFO_X25519.length !== 21) {\n throw new Error('INFO_X25519 byte-length invariant violated (expected 21)');\n}\nif (INFO_MLKEM768X25519.length !== 29) {\n throw new Error('INFO_MLKEM768X25519 byte-length invariant violated (expected 29)');\n}\n\nconst EMPTY_SALT: Uint8Array = new Uint8Array(0);\nconst SEED_LENGTH = 32;\nconst DERIVED_LENGTH = 32;\n\nexport interface DerivedEd25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface DerivedX25519KeyPair {\n readonly secretKey: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nexport interface DerivedMlKem768X25519KeyPair {\n readonly secretSeed: Uint8Array;\n readonly publicKey: Uint8Array;\n}\n\nfunction assertSeedLength(seed: Uint8Array): void {\n if (seed.length !== SEED_LENGTH) {\n throw new SeedDeriveError(\n 'INVALID_SEED_LENGTH',\n `seed must be exactly 32 bytes, got ${seed.length}`,\n );\n }\n}\n\nexport function deriveEd25519KeypairFromSeed(seed: Uint8Array): DerivedEd25519KeyPair {\n assertSeedLength(seed);\n const secretKey = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_ED25519,\n length: DERIVED_LENGTH,\n });\n const publicKey = getPublicKeyEd25519({ seed: secretKey });\n return { secretKey, publicKey };\n}\n\nexport function deriveX25519KeypairFromSeed(seed: Uint8Array): DerivedX25519KeyPair {\n assertSeedLength(seed);\n const secretKey = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_X25519,\n length: DERIVED_LENGTH,\n });\n const publicKey = x25519PublicKey({ secretKey });\n return { secretKey, publicKey };\n}\n\nexport function deriveMlKem768X25519KeypairFromSeed(\n seed: Uint8Array,\n): DerivedMlKem768X25519KeyPair {\n assertSeedLength(seed);\n // The 32-byte HKDF output IS the X-Wing root seed: keygen re-expands the\n // ML-KEM coins and the X25519 scalar from it, so the derived keypair's\n // secretSeed equals this value.\n const xwingSeed = hkdfSha256({\n ikm: seed,\n salt: EMPTY_SALT,\n info: INFO_MLKEM768X25519,\n length: DERIVED_LENGTH,\n });\n return mlkem768x25519Keygen(xwingSeed);\n}\n","// Minimal BIP-173 bech32 encoder used to format age-style recipient strings.\n//\n// This package's dependency policy keeps the runtime import graph to a small,\n// audited set of cryptographic libraries, so we inline the exact bech32\n// algorithm here rather than pull in a general-purpose base-encoding library.\n// Output is byte-identical to the no-length-limit form of a standard bech32\n// encoder (`encode(hrp, toWords(bytes))` with the 90-char BIP-173 cap\n// disabled): age recipients exceed that cap — an X-Wing recipient is ~1960\n// characters — so the limit must be off.\n\nconst BECH32_ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nconst ENCODING_CONST = 1; // BIP-173 bech32 (not bech32m).\n\nfunction polymodStep(pre: number): number {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1) chk ^= POLYMOD_GENERATORS[i]!;\n }\n return chk;\n}\n\n// 8-bit bytes → 5-bit words, padding the final partial group with zero bits.\nfunction bytesToWords(bytes: Uint8Array): number[] {\n const words: number[] = [];\n let carry = 0;\n let pos = 0;\n const mask = (1 << 5) - 1;\n for (const n of bytes) {\n carry = (carry << 8) | n;\n pos += 8;\n for (; pos >= 5; pos -= 5) words.push((carry >> (pos - 5)) & mask);\n carry &= (1 << pos) - 1;\n }\n if (pos > 0) words.push((carry << (5 - pos)) & mask);\n return words;\n}\n\nfunction checksum(prefix: string, words: number[]): string {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error(`bech32: invalid prefix (${prefix})`);\n chk = polymodStep(chk) ^ (c >> 5);\n }\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n for (let i = 0; i < 6; i++) chk = polymodStep(chk);\n chk ^= ENCODING_CONST;\n let out = '';\n for (let i = 0; i < 6; i++) out += BECH32_ALPHABET[(chk >> (5 * (5 - i))) & 31];\n return out;\n}\n\n// Encode raw bytes to a bech32 string with NO length limit. `prefix` is the HRP.\nexport function bech32EncodeNoLimit(prefix: string, bytes: Uint8Array): string {\n if (prefix.length === 0) throw new Error('bech32: empty prefix');\n const words = bytesToWords(bytes);\n let payload = '';\n for (const w of words) payload += BECH32_ALPHABET[w];\n const lowered = prefix.toLowerCase();\n return `${lowered}1${payload}${checksum(lowered, words)}`;\n}\n\n// Recompute the polymod over the HRP + every data word (the trailing six being\n// the checksum) and test it against the encoding constant. True iff the string\n// carries a valid bech32 checksum.\nfunction checksumValid(prefix: string, words: number[]): boolean {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) >> 5);\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n return chk === ENCODING_CONST;\n}\n\n// 5-bit words → 8-bit bytes (the inverse of `bytesToWords`). Rejects\n// non-canonical padding: any leftover must be fewer than 5 bits and all zero,\n// matching the zero-fill `bytesToWords` applies to a final partial group.\nfunction wordsToBytes(words: number[]): Uint8Array {\n const out: number[] = [];\n let carry = 0;\n let pos = 0;\n for (const w of words) {\n carry = (carry << 5) | w;\n pos += 5;\n for (; pos >= 8; pos -= 8) out.push((carry >> (pos - 8)) & 0xff);\n carry &= (1 << pos) - 1;\n }\n if (pos >= 5 || carry !== 0) throw new Error('bech32: non-canonical padding');\n return Uint8Array.from(out);\n}\n\n// Decode a bech32 string with NO length limit, verifying the checksum. Returns\n// the lower-cased HRP and the decoded data bytes. The inverse of\n// `bech32EncodeNoLimit`. The separator is the last `1` in the string, so HRPs\n// that themselves contain a `1` (e.g. the `age1pqc` recipient prefix) round-trip\n// correctly.\nexport function bech32DecodeNoLimit(input: string): { hrp: string; bytes: Uint8Array } {\n if (input.length === 0) throw new Error('bech32: empty string');\n const hasLower = input !== input.toUpperCase();\n const hasUpper = input !== input.toLowerCase();\n if (hasLower && hasUpper) throw new Error('bech32: mixed-case string');\n const s = input.toLowerCase();\n const sep = s.lastIndexOf('1');\n if (sep < 1) throw new Error('bech32: missing human-readable prefix');\n if (s.length - sep - 1 < 6) throw new Error('bech32: data too short for checksum');\n const hrp = s.slice(0, sep);\n for (let i = 0; i < hrp.length; i++) {\n const c = hrp.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error('bech32: invalid prefix character');\n }\n const words: number[] = [];\n for (let i = sep + 1; i < s.length; i++) {\n const v = BECH32_ALPHABET.indexOf(s[i]!);\n if (v === -1) throw new Error('bech32: invalid data character');\n words.push(v);\n }\n if (!checksumValid(hrp, words)) throw new Error('bech32: bad checksum');\n return { hrp, bytes: wordsToBytes(words.slice(0, words.length - 6)) };\n}\n","// Encodes a raw KEM public key to a bech32 age-style recipient string — the\n// form a sender uses to address a sealed PoE record.\n//\n// • X25519 (32 bytes) → \"age1…\"\n// • X-Wing / ML-KEM-768 + X25519 (1216 bytes) → \"age1pqc…\"\n//\n// The two HRPs make a recipient self-describing: a parser routes to the right\n// KEM purely from the bech32 prefix. We use the `age1pqc` HRP for the hybrid\n// key (upstream age v1.3.0 claims the shorter `age1pq` HRP for the same X-Wing\n// primitive; `age1pqc` avoids colliding with that wire identifier).\n//\n// The X-Wing public key derives for free from the same identity seed via\n// `deriveMlKem768X25519KeypairFromSeed`, so every identity always has one and\n// can RECEIVE hybrid sealed records even when it publishes via the classical\n// X25519 path.\n\nimport { bech32DecodeNoLimit, bech32EncodeNoLimit } from './bech32';\n\nconst X25519_HRP = 'age';\nconst XWING_HRP = 'age1pqc';\nconst X25519_PUBLIC_KEY_BYTES = 32;\nconst XWING_PUBLIC_KEY_BYTES = 1216;\n\n// The KEM a recipient string addresses, inferred from its bech32 HRP.\nexport type RecipientKem = 'x25519' | 'mlkem768x25519';\n\nexport interface ParsedAgeRecipient {\n readonly kem: RecipientKem;\n readonly publicKey: Uint8Array;\n}\n\nexport function encodeAgeX25519Recipient(publicKey: Uint8Array): string {\n if (publicKey.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeX25519Recipient: publicKey must be exactly 32 bytes');\n }\n return bech32EncodeNoLimit(X25519_HRP, publicKey);\n}\n\nexport function encodeAgeXWingRecipient(publicKey: Uint8Array): string {\n if (publicKey.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeXWingRecipient: publicKey must be exactly 1216 bytes');\n }\n return bech32EncodeNoLimit(XWING_HRP, publicKey);\n}\n\n// Decode an age-style recipient string back to its raw KEM public key, routing\n// on the bech32 HRP. The inverse of `encodeAgeX25519Recipient` /\n// `encodeAgeXWingRecipient`: a sender can take a recipient string a peer shared\n// and recover the exact public key (and which KEM it belongs to) needed to seal\n// a record to them. Surrounding whitespace is tolerated so pasted strings parse.\n// Throws on an unknown HRP, a bad checksum, or a key length that does not match\n// the HRP's KEM.\nexport function parseAgeRecipient(recipient: string): ParsedAgeRecipient {\n if (typeof recipient !== 'string') {\n throw new Error('parseAgeRecipient: recipient must be a string');\n }\n const { hrp, bytes } = bech32DecodeNoLimit(recipient.trim());\n if (hrp === X25519_HRP) {\n if (bytes.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age recipient must carry a 32-byte X25519 key');\n }\n return { kem: 'x25519', publicKey: bytes };\n }\n if (hrp === XWING_HRP) {\n if (bytes.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age1pqc recipient must carry a 1216-byte X-Wing key');\n }\n return { kem: 'mlkem768x25519', publicKey: bytes };\n }\n throw new Error(`parseAgeRecipient: unrecognized recipient prefix \"${hrp}\"`);\n}\n","export class AeadVerificationError extends Error {\n readonly code: string = 'aead_verification_failed';\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'AeadVerificationError';\n }\n}\n","import { chacha20poly1305 } from '@noble/ciphers/chacha.js';\n\nimport { AeadVerificationError } from './errors';\n\nexport interface ChaCha20Poly1305EncryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly plaintext: Uint8Array;\n}\n\nexport interface ChaCha20Poly1305DecryptOpts {\n readonly key: Uint8Array;\n readonly nonce: Uint8Array;\n readonly aad: Uint8Array;\n readonly ciphertext: Uint8Array;\n}\n\nexport function chacha20Poly1305Encrypt(opts: ChaCha20Poly1305EncryptOpts): Uint8Array {\n return chacha20poly1305(opts.key, opts.nonce, opts.aad).encrypt(opts.plaintext);\n}\n\nexport function chacha20Poly1305Decrypt(opts: ChaCha20Poly1305DecryptOpts): Uint8Array {\n try {\n return chacha20poly1305(opts.key, opts.nonce, opts.aad).decrypt(opts.ciphertext);\n } catch (cause) {\n throw new AeadVerificationError('chacha20-poly1305 decrypt failed', { cause });\n }\n}\n","// Sealed-PoE construction error taxonomy (wire-shape + partitioning-oracle\n// pre-checks + caller-input validation).\n//\n// Codes whose concept exists in the wire error-code registry reuse the registry\n// string verbatim (UNSUPPORTED_ENVELOPE_SCHEME, UNSUPPORTED_AEAD_ALG,\n// ENC_PASSPHRASE_EMPTY, ...), so a consumer correlating construction failures\n// with validator/verifier reports sees one vocabulary. Conditions that exist\n// only at the construction API boundary (raw caller-input lengths, deterministic\n// test-override mismatches) carry construction-local names with no wire\n// counterpart.\n\nexport type EciesSealedPoeErrorCode =\n // Wire-registry codes (same concept, same string).\n | 'ENC_SLOTS_EMPTY'\n | 'ENC_SLOTS_MAC_INVALID_LENGTH'\n | 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL'\n | 'ENC_SLOTS_TOO_MANY'\n | 'ENC_ENVELOPE_TOO_LARGE'\n | 'ENC_REQUIRES_CONTENT_HASH'\n | 'ENC_PASSPHRASE_EMPTY'\n | 'ENC_PASSPHRASE_UNNORMALIZABLE'\n | 'ENC_PASSPHRASE_ALG_UNSUPPORTED'\n | 'ENC_PASSPHRASE_SALT_TOO_SHORT'\n | 'ENC_PASSPHRASE_SALT_TOO_LONG'\n | 'ENC_PASSPHRASE_ARGON2_PARAMS_TOO_LOW'\n | 'KEM_EPK_LENGTH_MISMATCH'\n | 'KEM_CT_LENGTH_MISMATCH'\n | 'NONCE_LENGTH_MISMATCH'\n | 'WRAP_LENGTH_MISMATCH'\n | 'UNSUPPORTED_ENVELOPE_SCHEME'\n | 'UNSUPPORTED_AEAD_ALG'\n | 'UNSUPPORTED_KEM_ALG'\n | 'KDF_DERIVATION_FAILED'\n // Construction-local codes (no wire counterpart).\n | 'INVALID_CEK_LENGTH'\n | 'INVALID_EPHEMERAL_SECRET_LENGTH'\n | 'EPHEMERAL_SECRETS_COUNT_MISMATCH'\n | 'INVALID_RECIPIENT_KEY'\n | 'INVALID_PASSPHRASE_PARAMS'\n | 'PASSPHRASE_INPUT_TOO_LONG';\n\nexport class EciesSealedPoeError extends Error {\n readonly code: EciesSealedPoeErrorCode;\n\n constructor(code: EciesSealedPoeErrorCode, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'EciesSealedPoeError';\n this.code = code;\n }\n}\n","// chacha20-poly1305-stream64k: the segmented STREAM content format for sealed\n// PoE (the age v1 STREAM layout).\n//\n// cipher : ChaCha20-Poly1305 (RFC 8439; 12-byte nonce, 16-byte tag)\n// chunk size : 65536 plaintext bytes per non-final chunk\n// chunk nonce : uint88_be(counter) || final_flag — counter starts at 0,\n// +1 per chunk; final_flag is 0x01 on the final chunk,\n// 0x00 otherwise\n// per-chunk AAD : empty (all context binds transitively through the\n// payload_key, whose CEK is committed by slots_mac or the\n// passphrase commitment header)\n// final chunk : 0..65536 plaintext bytes; zero-length only when the whole\n// plaintext is empty (an empty plaintext is exactly one\n// zero-length final chunk — a lone 16-byte tag)\n//\n// The counter nonces are safe because the payload_key is single-use (a fresh\n// CEK salted by the envelope-unique enc.nonce), so no two streams ever share a\n// (key, nonce) pair. The final flag domain-separates the last chunk, which is\n// what makes truncation detectable.\n//\n// Layout violations — a tag failure, a truncated stream, data after the final\n// chunk, a non-final chunk shorter than CHUNK_SIZE, a zero-length final chunk\n// on a non-empty stream — all surface as StreamTamperedError; the caller maps\n// it to the single generic decryption failure. Each chunk's tag is verified\n// before that chunk's plaintext is released, but the whole-plaintext hash\n// recheck is post-hoc: incremental consumers MUST treat released bytes as\n// tentative until it passes.\n\nimport { chacha20Poly1305Decrypt, chacha20Poly1305Encrypt } from '../aead/chacha20-poly1305';\nimport { AeadVerificationError } from '../aead/errors';\n\n// Pinned format constants. The 88-bit counter admits at most 2^88 chunks, far\n// above any realisable payload, so the format imposes no cryptographic payload\n// ceiling — the practical maximum is a deployment denial-of-service policy, not\n// a wire constant.\nexport const CHUNK_SIZE = 65536;\nexport const TAG_SIZE = 16;\n\nconst NONCE_LENGTH = 12;\nconst COUNTER_LENGTH = 11;\nconst SEALED_CHUNK_SIZE = CHUNK_SIZE + TAG_SIZE;\nconst PAYLOAD_KEY_LENGTH = 32;\nconst EMPTY_AAD: Uint8Array = new Uint8Array(0);\n\n// Authenticated-decryption failure of the stream: a chunk tag did not verify or\n// the chunk layout violates the format rules. Callers surface it as the single\n// generic decryption failure (the TAMPERED_CIPHERTEXT outcome).\nexport class StreamTamperedError extends Error {\n readonly code = 'TAMPERED_CIPHERTEXT' as const;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'StreamTamperedError';\n }\n}\n\n// Shared chunk-nonce state machine: an 11-byte big-endian counter followed by\n// the final-flag byte. The counter increments once per chunk; using a chunk\n// machine after its final chunk is a caller error, never silently accepted.\nclass ChunkNonce {\n private readonly nonce = new Uint8Array(NONCE_LENGTH);\n private finished = false;\n\n next(final: boolean): Uint8Array {\n if (this.finished) {\n throw new Error('STREAM: no chunks may follow the final chunk');\n }\n if (final) {\n this.finished = true;\n this.nonce[COUNTER_LENGTH] = 0x01;\n }\n const out = this.nonce.slice();\n this.increment();\n return out;\n }\n\n get done(): boolean {\n return this.finished;\n }\n\n private increment(): void {\n for (let i = COUNTER_LENGTH - 1; i >= 0; i--) {\n const v = ((this.nonce[i] as number) + 1) & 0xff;\n this.nonce[i] = v;\n if (v !== 0) return;\n }\n // 2^88 chunks exhausted — unreachable for any realisable payload.\n throw new Error('STREAM: chunk counter overflow');\n }\n}\n\nfunction assertPayloadKey(payloadKey: Uint8Array): void {\n if (payloadKey.length !== PAYLOAD_KEY_LENGTH) {\n throw new Error(\n `STREAM: payloadKey MUST be exactly ${PAYLOAD_KEY_LENGTH} bytes, got ${payloadKey.length}`,\n );\n }\n}\n\n// Incremental sealer. Feed plaintext chunk by chunk: every non-final chunk MUST\n// be exactly CHUNK_SIZE bytes; the final chunk carries 0..CHUNK_SIZE bytes, and\n// a zero-length final chunk is admissible only as the sole chunk of an empty\n// plaintext.\nexport class StreamSealer {\n private readonly payloadKey: Uint8Array;\n private readonly nonce = new ChunkNonce();\n private chunkIndex = 0;\n\n constructor(payloadKey: Uint8Array) {\n assertPayloadKey(payloadKey);\n this.payloadKey = payloadKey;\n }\n\n sealChunk(plaintext: Uint8Array, final: boolean): Uint8Array {\n if (!final && plaintext.length !== CHUNK_SIZE) {\n throw new Error(\n `STREAM: non-final chunk MUST carry exactly ${CHUNK_SIZE} plaintext bytes, got ${plaintext.length}`,\n );\n }\n if (final && plaintext.length > CHUNK_SIZE) {\n throw new Error(\n `STREAM: final chunk MUST carry at most ${CHUNK_SIZE} plaintext bytes, got ${plaintext.length}`,\n );\n }\n if (final && plaintext.length === 0 && this.chunkIndex > 0) {\n throw new Error(\n 'STREAM: a zero-length final chunk is admissible only for an empty plaintext',\n );\n }\n const sealed = chacha20Poly1305Encrypt({\n key: this.payloadKey,\n nonce: this.nonce.next(final),\n aad: EMPTY_AAD,\n plaintext,\n });\n this.chunkIndex += 1;\n return sealed;\n }\n}\n\n// Incremental opener. Feed sealed chunks in order with the expected final flag;\n// each chunk's plaintext is released only after its tag verifies (and is still\n// tentative until the caller's whole-plaintext hash recheck passes). Chunk\n// boundaries are the caller's responsibility in incremental use; `streamOpen`\n// derives them from the blob length.\nexport class StreamOpener {\n private readonly payloadKey: Uint8Array;\n private readonly nonce = new ChunkNonce();\n private chunkIndex = 0;\n\n constructor(payloadKey: Uint8Array) {\n assertPayloadKey(payloadKey);\n this.payloadKey = payloadKey;\n }\n\n openChunk(sealedChunk: Uint8Array, final: boolean): Uint8Array {\n if (sealedChunk.length < TAG_SIZE) {\n throw new StreamTamperedError(\n `STREAM: sealed chunk shorter than the ${TAG_SIZE}-byte tag floor`,\n );\n }\n if (!final && sealedChunk.length !== SEALED_CHUNK_SIZE) {\n throw new StreamTamperedError(\n `STREAM: non-final sealed chunk MUST be exactly ${SEALED_CHUNK_SIZE} bytes, got ${sealedChunk.length}`,\n );\n }\n if (final && sealedChunk.length > SEALED_CHUNK_SIZE) {\n throw new StreamTamperedError(\n `STREAM: final sealed chunk MUST be at most ${SEALED_CHUNK_SIZE} bytes, got ${sealedChunk.length}`,\n );\n }\n if (final && sealedChunk.length === TAG_SIZE && this.chunkIndex > 0) {\n throw new StreamTamperedError('STREAM: zero-length final chunk on a non-empty stream');\n }\n let plaintext: Uint8Array;\n try {\n plaintext = chacha20Poly1305Decrypt({\n key: this.payloadKey,\n nonce: this.nonce.next(final),\n aad: EMPTY_AAD,\n ciphertext: sealedChunk,\n });\n } catch (e) {\n if (!(e instanceof AeadVerificationError)) throw e;\n throw new StreamTamperedError(`STREAM: chunk ${this.chunkIndex} tag verification failed`, {\n cause: e,\n });\n }\n this.chunkIndex += 1;\n return plaintext;\n }\n}\n\n// Whole-buffer seal: split the plaintext into CHUNK_SIZE chunks (an empty\n// plaintext is exactly one zero-length final chunk) and concatenate the sealed\n// chunks.\nexport function streamSeal(args: { payloadKey: Uint8Array; plaintext: Uint8Array }): Uint8Array {\n const { plaintext } = args;\n const sealer = new StreamSealer(args.payloadKey);\n const chunkCount = Math.max(1, Math.ceil(plaintext.length / CHUNK_SIZE));\n const out = new Uint8Array(plaintext.length + chunkCount * TAG_SIZE);\n let offset = 0;\n for (let i = 0; i < chunkCount; i++) {\n const final = i === chunkCount - 1;\n const chunk = plaintext.subarray(\n i * CHUNK_SIZE,\n Math.min((i + 1) * CHUNK_SIZE, plaintext.length),\n );\n const sealed = sealer.sealChunk(chunk, final);\n out.set(sealed, offset);\n offset += sealed.length;\n }\n return out;\n}\n\n// Whole-buffer open. The chunk boundaries are fully determined by the blob\n// length: every non-final sealed chunk is exactly SEALED_CHUNK_SIZE bytes and\n// the final sealed chunk is whatever remains (TAG_SIZE..SEALED_CHUNK_SIZE). A\n// blob below the 16-byte floor, a tail that cannot form a well-formed final\n// chunk, or a zero-length final chunk on a non-empty stream is malformed before\n// any tag is checked. Truncation that removes the final chunk leaves a stream\n// whose last chunk was sealed with the 0x00 flag but is opened with the 0x01\n// flag nonce, so its tag fails — the final-flag byte is the truncation\n// detector.\nexport function streamOpen(args: { payloadKey: Uint8Array; ciphertext: Uint8Array }): Uint8Array {\n const { ciphertext } = args;\n const total = ciphertext.length;\n if (total < TAG_SIZE) {\n throw new StreamTamperedError(\n `STREAM: ciphertext shorter than the ${TAG_SIZE}-byte single-tag floor`,\n );\n }\n const rem = total % SEALED_CHUNK_SIZE;\n let nonFinalCount: number;\n let finalSealedLength: number;\n if (rem === 0) {\n nonFinalCount = total / SEALED_CHUNK_SIZE - 1;\n finalSealedLength = SEALED_CHUNK_SIZE;\n } else if (rem >= TAG_SIZE) {\n nonFinalCount = (total - rem) / SEALED_CHUNK_SIZE;\n finalSealedLength = rem;\n } else {\n throw new StreamTamperedError('STREAM: trailing bytes cannot form a well-formed final chunk');\n }\n if (nonFinalCount > 0 && finalSealedLength === TAG_SIZE) {\n throw new StreamTamperedError('STREAM: zero-length final chunk on a non-empty stream');\n }\n\n const opener = new StreamOpener(args.payloadKey);\n const out = new Uint8Array(nonFinalCount * CHUNK_SIZE + finalSealedLength - TAG_SIZE);\n let readOffset = 0;\n let writeOffset = 0;\n for (let i = 0; i < nonFinalCount; i++) {\n const plaintext = opener.openChunk(\n ciphertext.subarray(readOffset, readOffset + SEALED_CHUNK_SIZE),\n false,\n );\n out.set(plaintext, writeOffset);\n readOffset += SEALED_CHUNK_SIZE;\n writeOffset += CHUNK_SIZE;\n }\n const finalPlaintext = opener.openChunk(ciphertext.subarray(readOffset), true);\n out.set(finalPlaintext, writeOffset);\n return out;\n}\n","import { cdeDecodeOptions, decode, encode } from 'cbor2';\nimport { sortCoreDeterministic } from 'cbor2/sorts';\n\nimport { CanonicalCborError } from './errors';\n\nexport type CanonicalCborValue =\n | null\n | boolean\n | number\n | bigint\n | string\n | Uint8Array\n | readonly CanonicalCborValue[]\n | { readonly [key: string]: CanonicalCborValue }\n | ReadonlyMap<string | number, CanonicalCborValue>;\n\nexport function encodeCanonicalCbor(value: CanonicalCborValue): Uint8Array {\n return encode(value, {\n cde: true,\n collapseBigInts: true,\n rejectDuplicateKeys: true,\n sortKeys: sortCoreDeterministic,\n });\n}\n\nexport function decodeCanonicalCbor(bytes: Uint8Array): unknown {\n try {\n return decode(bytes, {\n ...cdeDecodeOptions,\n rejectStreaming: true,\n rejectDuplicateKeys: true,\n // A Label 309 record carries integers, byte/text strings, arrays, maps and\n // `null` — and nothing else. Without these rejections the major-type-7\n // surface leaks into the decoder: a float16/32/64 that happens to hold an\n // integral value (e.g. 1.0) silently decodes to the integer 1 and passes\n // a `z.literal(1)` / Number.isInteger schema check, so two byte strings\n // that are NOT byte-identical canonicalise to the same record. That\n // breaks the cross-implementation parity invariant (the Python twin\n // already rejects non-integer `v` / `enc.scheme` outright). Reject the\n // whole non-record surface — floats, negative zero, undefined, and\n // non-{true,false,null} simple values — so any such input surfaces as\n // MALFORMED_CBOR via mapDecodeError rather than decoding to a look-alike.\n rejectFloats: true,\n rejectNegativeZero: true,\n rejectUndefined: true,\n rejectSimple: true,\n });\n } catch (cause) {\n throw mapDecodeError(cause);\n }\n}\n\nfunction mapDecodeError(cause: unknown): CanonicalCborError {\n const message = cause instanceof Error ? cause.message : String(cause);\n const lower = message.toLowerCase();\n // Every canonical-decode violation collapses to the single public taxonomy\n // code MALFORMED_CBOR: indefinite-length (streaming) items, duplicate keys,\n // non-canonical (unsorted) key ordering, non-minimal integer encodings, and\n // invalid UTF-8 in text strings. cbor2 raises the SAME \"Duplicate or out of\n // order key\" message for both true duplicates AND distinct-but-unsorted keys,\n // so the two are indistinguishable by message — and per the Label 309 taxonomy\n // both belong under MALFORMED_CBOR anyway. The specific cause survives in the\n // human-readable message below; for indefinite-length we state it explicitly\n // so the diagnostic is not lost when the code is collapsed.\n const isIndefinite = lower.includes('streaming') || lower.includes('indefinite');\n const detail = isIndefinite\n ? `indefinite-length items are not permitted in canonical CBOR: ${message}`\n : message;\n return new CanonicalCborError('MALFORMED_CBOR', `cbor decode failed: ${detail}`, { cause });\n}\n","// Shared, byte-critical pieces of the sealed-PoE construction that the producer\n// (wrap / passphrase seal) and every verifier (unwrap, trial-decrypt,\n// passphrase open) MUST compute byte-for-byte identically:\n//\n// 1. The item-hashes digest `hashes_hash`.\n// 2. The slots transcript, its SHA-256 `slots_hash`, and the CEK-keyed\n// `slots_mac`.\n// 3. The passphrase transcript, its SHA-256 `pw_hash`, and the CEK-keyed\n// in-ciphertext `commitment`.\n// 4. The content `payload_key` derivations (both key paths).\n// 5. Both per-slot KEK HKDF salts (classical and hybrid).\n//\n// Keeping these in one module is the interop guarantee: a single divergence in\n// the canonical encoding silently yields a `slots_mac`, a commitment, or an\n// AEAD tag that another implementation cannot reproduce, with no typed error to\n// localise the fault. There is exactly one shared implementation, imported by\n// both sides.\n\nimport { hmac } from '@noble/hashes/hmac.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n\nimport { encodeCanonicalCbor, type CanonicalCborValue } from '../cbor/canonical';\nimport { hkdfSha256 } from '../kdf/hkdf';\n\nimport { EciesSealedPoeError } from './errors';\nimport type { Mlkem768X25519Slot, SealedKem, X25519Slot } from './wrap';\n\n// Internal domain-separation labels. Each is exact ASCII with no terminator and\n// no length prefix; each is a fixed constant of the scheme, never serialised on\n// the wire and never registry-selectable. The byte-length invariants below keep\n// the SCREAMING_SNAKE constants in sync with the ASCII literals every conformant\n// verifier hashes against.\n\n// SHA-256 prefix for the item-hashes digest `hashes_hash`.\nexport const CARDANO_POE_ITEM_HASHES_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-item-hashes-v1',\n);\n// SHA-256 prefix for the slots-transcript hash `slots_hash`.\nexport const CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-slots-transcript-v1',\n);\n// SHA-256 prefix for the passphrase-transcript hash `pw_hash`.\nexport const CARDANO_POE_PASSPHRASE_TRANSCRIPT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-passphrase-transcript-v1',\n);\n// HKDF info for the slot-set MAC key.\nexport const CARDANO_POE_HKDF_INFO_SLOTS_MAC: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-slots-mac-v1',\n);\n// HKDF info for the passphrase commitment MAC key.\nexport const CARDANO_POE_HKDF_INFO_PASSPHRASE_MAC: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-passphrase-mac-v1',\n);\n// HKDF info for the slots-path content `payload_key`.\nexport const CARDANO_POE_HKDF_INFO_PAYLOAD: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-payload-v1',\n);\n// HKDF info for the passphrase-path content `payload_key`.\nexport const CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-payload-passphrase-v1',\n);\n// SHA-256 prefix for the classical (x25519) per-slot KEK HKDF salt.\nexport const CARDANO_POE_X25519_KEK_SALT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-x25519-kek-salt-v1',\n);\n// SHA-256 prefix for the hybrid (X-Wing) per-slot KEK HKDF salt.\nexport const CARDANO_POE_XWING_KEK_SALT_PREFIX: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-xwing-kek-salt-v1',\n);\n\nif (CARDANO_POE_ITEM_HASHES_PREFIX.length !== 26) {\n throw new Error('CARDANO_POE_ITEM_HASHES_PREFIX byte-length invariant violated (expected 26)');\n}\nif (CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length !== 31) {\n throw new Error(\n 'CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX byte-length invariant violated (expected 31)',\n );\n}\nif (CARDANO_POE_PASSPHRASE_TRANSCRIPT_PREFIX.length !== 36) {\n throw new Error(\n 'CARDANO_POE_PASSPHRASE_TRANSCRIPT_PREFIX byte-length invariant violated (expected 36)',\n );\n}\nif (CARDANO_POE_HKDF_INFO_SLOTS_MAC.length !== 24) {\n throw new Error('CARDANO_POE_HKDF_INFO_SLOTS_MAC byte-length invariant violated (expected 24)');\n}\nif (CARDANO_POE_HKDF_INFO_PASSPHRASE_MAC.length !== 29) {\n throw new Error(\n 'CARDANO_POE_HKDF_INFO_PASSPHRASE_MAC byte-length invariant violated (expected 29)',\n );\n}\nif (CARDANO_POE_HKDF_INFO_PAYLOAD.length !== 22) {\n throw new Error('CARDANO_POE_HKDF_INFO_PAYLOAD byte-length invariant violated (expected 22)');\n}\nif (CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE.length !== 33) {\n throw new Error(\n 'CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE byte-length invariant violated (expected 33)',\n );\n}\nif (CARDANO_POE_X25519_KEK_SALT_PREFIX.length !== 30) {\n throw new Error(\n 'CARDANO_POE_X25519_KEK_SALT_PREFIX byte-length invariant violated (expected 30)',\n );\n}\nif (CARDANO_POE_XWING_KEK_SALT_PREFIX.length !== 29) {\n throw new Error('CARDANO_POE_XWING_KEK_SALT_PREFIX byte-length invariant violated (expected 29)');\n}\n\n// Scheme-fixed constant pinning the passphrase normalization profile the CEK was\n// derived under. Fed into the passphrase transcript; never serialised on the\n// wire.\nexport const CARDANO_POE_PW_NORM_PROFILE = 'cardano-poe-pw-norm-v1' as const;\n\n// Verifier-side resource bounds a public parser MUST enforce BEFORE invoking any\n// KEM/AEAD primitive, so a malformed envelope cannot drive unbounded work. Both\n// are deployment-pinned reference constants (not wire fields); deployments MAY\n// tighten them. They sit far above the ~16 KiB Cardano transaction-metadata\n// ceiling that bounds honest records, so a conformant record never trips them.\n//\n// • MAX_SLOTS — the maximum slot count; an envelope with more slots is\n// rejected outright.\n// • MAX_DECODED_ENVELOPE_BYTES — a backstop on the decoded envelope's\n// aggregate byte size (nonce + slots_mac + every per-slot wire field),\n// bounding the work even before the slot-count cap would.\nexport const MAX_SLOTS = 1024;\nexport const MAX_DECODED_ENVELOPE_BYTES = 65536;\n\nconst EMPTY_SALT: Uint8Array = new Uint8Array(0);\n\n// The item's plaintext-hash claim: registered algorithm identifier → digest\n// bytes, exactly as carried in the record body. Both key paths bind this map\n// (via `hashes_hash`) into their commitment, so an envelope spliced onto an\n// item with a different hash claim is rejected before any ciphertext work.\nexport type ItemHashes = Readonly<Record<string, Uint8Array>>;\n\nfunction labelledSha256(prefix: Uint8Array, ...parts: ReadonlyArray<Uint8Array>): Uint8Array {\n let total = prefix.length;\n for (const p of parts) total += p.length;\n const message = new Uint8Array(total);\n message.set(prefix, 0);\n let offset = prefix.length;\n for (const p of parts) {\n message.set(p, offset);\n offset += p.length;\n }\n return sha256(message);\n}\n\n// SHA-256(\"cardano-poe-item-hashes-v1\" || canonicalEncode(item.hashes)).\n// The hashes map is encoded exactly as it appears in the record body\n// (registry-identifier keys → digest byte strings, canonical key order). An\n// `enc`-bearing item MUST declare at least one content hash — the ciphertext is\n// bound to the plaintext only through that digest — so an empty map is rejected\n// here, on both the producer and the verifier side.\nexport function itemHashesHash(hashes: ItemHashes): Uint8Array {\n if (Object.keys(hashes).length === 0) {\n throw new EciesSealedPoeError(\n 'ENC_REQUIRES_CONTENT_HASH',\n 'hashes MUST carry at least one content-hash entry',\n );\n }\n return labelledSha256(CARDANO_POE_ITEM_HASHES_PREFIX, encodeCanonicalCbor(hashes));\n}\n\n// SHA-256(\"cardano-poe-slots-transcript-v1\" || canonicalEncode(SLOTS_TRANSCRIPT)).\n// SLOTS_TRANSCRIPT is the closed seven-key map binding the cross-KEM header\n// fields (scheme, path, aead, kem, nonce) and the item's hash claim\n// (hashes_hash) to the on-wire slot set, so a relay that flips any header field\n// — or splices the envelope onto a different item — yields a different\n// `slots_hash` and the MAC fails. Computed ONCE per envelope and held constant\n// across the recipient trial-decrypt loop. The map keys are a SET — their wire\n// order is fixed by the canonical-encode sort, never hand-arranged here.\nexport function computeSlotsHash(args: {\n aead: string;\n kem: SealedKem;\n nonce: Uint8Array;\n slots: ReadonlyArray<X25519Slot | Mlkem768X25519Slot>;\n hashesHash: Uint8Array;\n}): Uint8Array {\n // The slot array is re-stated as explicit closed two-key maps (never the raw\n // caller objects), so an extra property on a caller's slot value can never\n // leak into the committed bytes.\n const slots: CanonicalCborValue =\n args.kem === 'x25519'\n ? (args.slots as ReadonlyArray<X25519Slot>).map((s) => ({ epk: s.epk, wrap: s.wrap }))\n : (args.slots as ReadonlyArray<Mlkem768X25519Slot>).map((s) => ({\n kem_ct: s.kem_ct,\n wrap: s.wrap,\n }));\n const transcript: CanonicalCborValue = {\n scheme: 1,\n path: 'slots',\n aead: args.aead,\n kem: args.kem,\n nonce: args.nonce,\n slots,\n hashes_hash: args.hashesHash,\n };\n return labelledSha256(CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX, encodeCanonicalCbor(transcript));\n}\n\n// SHA-256(\"cardano-poe-passphrase-transcript-v1\" || canonicalEncode(PASSPHRASE_TRANSCRIPT)).\n// PASSPHRASE_TRANSCRIPT is the closed six-key map (with `passphrase` itself a\n// closed sub-map) binding the header fields, the Argon2id parameters, the\n// normalization profile, and the item's hash claim into the in-ciphertext\n// commitment. There is NO `kem` key on this path. The `normalization` value is\n// the scheme-fixed profile constant, pinned into the transcript and never\n// serialised on the wire.\nexport function computePassphraseHash(args: {\n aead: string;\n nonce: Uint8Array;\n hashesHash: Uint8Array;\n salt: Uint8Array;\n params: { m: number; t: number; p: number };\n}): Uint8Array {\n const transcript: CanonicalCborValue = {\n scheme: 1,\n path: 'passphrase',\n aead: args.aead,\n nonce: args.nonce,\n hashes_hash: args.hashesHash,\n passphrase: {\n alg: 'argon2id',\n salt: args.salt,\n params: { m: args.params.m, t: args.params.t, p: args.params.p },\n normalization: CARDANO_POE_PW_NORM_PROFILE,\n },\n };\n return labelledSha256(CARDANO_POE_PASSPHRASE_TRANSCRIPT_PREFIX, encodeCanonicalCbor(transcript));\n}\n\n// Slot-set MAC: HMAC-SHA-256 keyed by an HKDF leaf of the CEK over the 32-byte\n// `slots_hash`. Pre-hashing the transcript only changes the HMAC message from\n// the full transcript to its SHA-256, leaving the CEK-keyed commitment intact.\n// The fixed 32-byte HKDF key structurally excludes the HMAC over-block-length\n// key ambiguity.\nexport function computeSlotsMac(args: { cek: Uint8Array; slotsHash: Uint8Array }): Uint8Array {\n const macKey = hkdfSha256({\n ikm: args.cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,\n length: 32,\n });\n return hmac(sha256, macKey, args.slotsHash);\n}\n\n// Passphrase-path key commitment: HMAC-SHA-256 keyed by an HKDF leaf of the CEK\n// over the 32-byte `pw_hash`. Prepended inside the ciphertext blob (never an\n// on-chain field), so testing a passphrase guess requires possession of the\n// blob itself.\nexport function computePassphraseCommitment(args: {\n cek: Uint8Array;\n pwHash: Uint8Array;\n}): Uint8Array {\n const macKey = hkdfSha256({\n ikm: args.cek,\n salt: EMPTY_SALT,\n info: CARDANO_POE_HKDF_INFO_PASSPHRASE_MAC,\n length: 32,\n });\n return hmac(sha256, macKey, args.pwHash);\n}\n\n// Slots-path content key: HKDF-SHA-256(ikm=CEK, salt=enc.nonce, info=payload-v1).\n// The content is encrypted under this leaf of the CEK, never under the CEK\n// directly, so the wrap layer and the content layer never key the same primitive\n// on the same bytes. The envelope-unique nonce salt makes the key single-use,\n// which is what keeps the STREAM counter nonces collision-free.\nexport function slotsPayloadKey(args: { cek: Uint8Array; nonce: Uint8Array }): Uint8Array {\n return hkdfSha256({\n ikm: args.cek,\n salt: args.nonce,\n info: CARDANO_POE_HKDF_INFO_PAYLOAD,\n length: 32,\n });\n}\n\n// Passphrase-path content key: HKDF-SHA-256(ikm=CEK, salt=enc.nonce,\n// info=payload-passphrase-v1).\nexport function passphrasePayloadKey(args: { cek: Uint8Array; nonce: Uint8Array }): Uint8Array {\n return hkdfSha256({\n ikm: args.cek,\n salt: args.nonce,\n info: CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE,\n length: 32,\n });\n}\n\n// Classical (x25519) per-slot KEK salt:\n// SHA-256(\"cardano-poe-x25519-kek-salt-v1\" || enc.nonce || epk || pub_R).\n// The slot's own ephemeral anchors the KEK to a slot-unique value, `pub_R`\n// binds it to the specific recipient (defeating confused-deputy relay of the\n// ephemeral against a different recipient), and the envelope-unique `enc.nonce`\n// anchors it to one envelope — a CSPRNG failure that repeats KEM randomness\n// across records degrades to mere linkability instead of reproducing a\n// (KEK, zero-nonce) wrap pair.\nexport function x25519KekSalt(args: {\n nonce: Uint8Array;\n epk: Uint8Array;\n pubR: Uint8Array;\n}): Uint8Array {\n return labelledSha256(CARDANO_POE_X25519_KEK_SALT_PREFIX, args.nonce, args.epk, args.pubR);\n}\n\n// Hybrid (mlkem768x25519) per-slot KEK salt:\n// SHA-256(\"cardano-poe-xwing-kek-salt-v1\" || enc.nonce || kem_ct || pub_R).\n// `kem_ct` is the slot's 1120-byte X-Wing ciphertext exactly as carried on the\n// wire and `pub_R` the 1216-byte X-Wing recipient public key — the same three\n// bindings as the classical salt, computed outside the KEM over the slot's own\n// wire bytes so it holds X-Wing as a black box.\nexport function xwingKekSalt(args: {\n nonce: Uint8Array;\n kemCt: Uint8Array;\n pubR: Uint8Array;\n}): Uint8Array {\n return labelledSha256(CARDANO_POE_XWING_KEK_SALT_PREFIX, args.nonce, args.kemCt, args.pubR);\n}\n","// Multi-recipient sealed-PoE wrap (age-style KEM-then-wrap slots + segmented\n// STREAM content). Wire-field names are fixed by the standard: scheme, aead,\n// kem, nonce, slots, slots_mac.\n//\n// Two KEM branches share one envelope shape, discriminated on the envelope-level\n// `kem` field:\n//\n// • kem: 'x25519' — classical age-style ECIES. Per-slot epk(32) + wrap(48).\n// • kem: 'mlkem768x25519' — X-Wing hybrid (ML-KEM-768 + X25519). Per-slot the\n// 1120-byte X-Wing ciphertext as a single byte\n// string (`kem_ct`) + wrap(48). No per-slot epk.\n//\n// The slot type is a discriminated union so every consumer is forced — at compile\n// time — to branch on the KEM before touching kem-specific fields.\n\nimport { randomBytes } from '@noble/ciphers/utils.js';\n\nimport { chacha20Poly1305Encrypt } from '../aead/chacha20-poly1305';\nimport {\n mlkem768x25519Encapsulate,\n MLKEM768X25519_ENC_LENGTH,\n MLKEM768X25519_ESEED_LENGTH,\n MLKEM768X25519_PUBLIC_KEY_LENGTH,\n} from '../kem/mlkem768x25519';\nimport { x25519Ecdh, x25519PublicKey } from '../kem/x25519';\nimport { hkdfSha256 } from '../kdf/hkdf';\n\nimport { EciesSealedPoeError } from './errors';\nimport { streamSeal } from './stream';\nimport {\n computeSlotsHash,\n computeSlotsMac,\n itemHashesHash,\n slotsPayloadKey,\n x25519KekSalt,\n xwingKekSalt,\n type ItemHashes,\n} from './transcript';\n\n// The envelope-level KEM discriminator.\nexport type SealedKem = 'x25519' | 'mlkem768x25519';\n\n// The sole registered content format under enc.scheme 1: ChaCha20-Poly1305 in\n// the 64 KiB segmented STREAM layout. Producers MUST emit this identifier\n// byte-exact.\nexport const SEALED_POE_AEAD = 'chacha20-poly1305-stream64k' as const;\n\n// HKDF info strings — fixed protocol labels for KEK derivation. Each doubles as\n// the per-slot wrap AEAD AAD (never empty AAD). Byte-length invariants enforce\n// that the SCREAMING_SNAKE constants stay in sync with the ASCII literals every\n// conformant verifier hashes against.\nexport const CARDANO_POE_HKDF_INFO_KEK: Uint8Array = new TextEncoder().encode('cardano-poe-kek-v1');\n// Hybrid (X-Wing) per-slot KEK label. Distinct from the classical label so a\n// KEK derived under one KEM can never collide with the other.\nexport const CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519: Uint8Array = new TextEncoder().encode(\n 'cardano-poe-kek-mlkem768x25519-v1',\n);\n\nconst ZERO_NONCE_12: Uint8Array = new Uint8Array(12);\nconst X25519_PUBLIC_KEY_LENGTH = 32 as const;\nconst X25519_SECRET_KEY_LENGTH = 32 as const;\nconst CEK_LENGTH = 32 as const;\nconst NONCE_LENGTH = 24 as const;\nconst WRAP_LENGTH = 48 as const;\nconst SLOTS_MAC_LENGTH = 32 as const;\n\nif (CARDANO_POE_HKDF_INFO_KEK.length !== 18) {\n throw new Error('CARDANO_POE_HKDF_INFO_KEK byte-length invariant violated (expected 18)');\n}\nif (CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519.length !== 33) {\n throw new Error(\n 'CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 byte-length invariant violated (expected 33)',\n );\n}\nif (ZERO_NONCE_12.length !== 12) {\n throw new Error('ZERO_NONCE_12 byte-length invariant violated (expected 12)');\n}\n\n// Classical per-slot wire shape: { epk: bstr(32), wrap: bstr(48) }.\nexport interface X25519Slot {\n readonly epk: Uint8Array;\n readonly wrap: Uint8Array;\n}\n\n// Hybrid per-slot wire shape: { kem_ct: bstr(1120), wrap: bstr(48) }. `kem_ct`\n// is the X-Wing ciphertext as a single byte string. There is NO per-slot epk\n// (the X25519 ephemeral is the trailing 32 bytes of kem_ct) and NO per-slot kem\n// field — the KEM identifier is hoisted to envelope scope (every slot shares it).\nexport interface Mlkem768X25519Slot {\n readonly kem_ct: Uint8Array;\n readonly wrap: Uint8Array;\n}\n\n// Sealed envelope wire shape (discriminated on `kem`).\nexport type SealedEnvelope =\n | {\n readonly scheme: 1;\n readonly aead: typeof SEALED_POE_AEAD;\n readonly kem: 'x25519';\n readonly nonce: Uint8Array;\n readonly slots: ReadonlyArray<X25519Slot>;\n readonly slots_mac: Uint8Array;\n }\n | {\n readonly scheme: 1;\n readonly aead: typeof SEALED_POE_AEAD;\n readonly kem: 'mlkem768x25519';\n readonly nonce: Uint8Array;\n readonly slots: ReadonlyArray<Mlkem768X25519Slot>;\n readonly slots_mac: Uint8Array;\n };\n\nexport interface SealedPoeOutput {\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n}\n\nexport interface WrapArgs {\n readonly plaintext: Uint8Array;\n // The item's plaintext-hash claim (registered algorithm id → digest bytes).\n // Its labelled digest is bound into the slots transcript, so the on-chain\n // slots_mac match also confirms the envelope belongs to this hash claim.\n readonly hashes: ItemHashes;\n readonly recipientPublicKeys: ReadonlyArray<Uint8Array>;\n // KEM branch selector. Defaults to 'x25519' for the classical path. The\n // recipient public-key length is validated against the chosen KEM.\n readonly kem?: SealedKem;\n readonly cek?: Uint8Array;\n readonly nonce?: Uint8Array;\n // Deterministic X25519 ephemeral scalars — x25519 branch only.\n readonly ephemeralSecrets?: ReadonlyArray<Uint8Array>;\n // Deterministic X-Wing encapsulation randomness (64 bytes each) — hybrid\n // branch only. One per recipient, parallel to recipientPublicKeys.\n readonly eseeds?: ReadonlyArray<Uint8Array>;\n readonly skipShuffle?: boolean;\n}\n\n// Anonymity invariant: wire ordering MUST NOT encode \"primary\n// recipient first\". A CSPRNG-keyed Fisher-Yates shuffle uniformly permutes the\n// slot array so trial-decrypt order leaks no recipient identity. The\n// slot-set HMAC is computed AFTER this shuffle, binding the on-wire order.\n//\n// Draw an unbiased index in [0, m) from a CSPRNG uint32 via rejection sampling.\n// A plain `u32 % m` skews toward the low residues whenever `m` does not divide\n// 2^32 evenly: the values [0, 2^32 mod m) each occur one extra time. This\n// function exists purely to produce a UNIFORM permutation, so the bias — though\n// cryptographically negligible — is exactly the property we cannot tolerate.\n// We reject any draw landing in the final partial block [limit, 2^32) and\n// redraw, leaving only the residues that map uniformly onto [0, m).\n// Exported so the rejection-bound arithmetic can be asserted directly in tests\n// without relying on a flaky statistical-distribution check.\nexport function uniformIndexBelow(m: number): number {\n // 2^32 mod m, computed without overflowing the 32-bit space.\n const limit = 0x1_0000_0000 - (0x1_0000_0000 % m);\n const buf = new Uint32Array(1);\n let x: number;\n do {\n crypto.getRandomValues(buf);\n x = buf[0] as number;\n } while (x >= limit);\n return x % m;\n}\n\nfunction csprngShuffle<T>(arr: T[]): void {\n for (let i = arr.length - 1; i > 0; i--) {\n const j = uniformIndexBelow(i + 1);\n const tmp = arr[i] as T;\n arr[i] = arr[j] as T;\n arr[j] = tmp;\n }\n}\n\n// Wrap the CEK for one classical recipient: age-style ECIES stanza with the\n// labelled-hash KEK salt binding nonce, epk, and pub_R.\nfunction wrapSlotX25519(args: {\n pubR: Uint8Array;\n privEph: Uint8Array | undefined;\n cek: Uint8Array;\n nonce: Uint8Array;\n slotIdx: number;\n}): X25519Slot {\n const privEph = args.privEph ?? randomBytes(X25519_SECRET_KEY_LENGTH);\n if (privEph.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_EPHEMERAL_SECRET_LENGTH',\n `ephemeralSecrets[${args.slotIdx}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${privEph.length}`,\n );\n }\n const epk = x25519PublicKey({ secretKey: privEph });\n const shared = x25519Ecdh({ secretKey: privEph, theirPublicKey: args.pubR });\n const kek = hkdfSha256({\n ikm: shared,\n salt: x25519KekSalt({ nonce: args.nonce, epk, pubR: args.pubR }),\n info: CARDANO_POE_HKDF_INFO_KEK,\n length: 32,\n });\n // Per-slot wrap AAD MUST be the 18-byte ASCII literal of the KEK info\n // string (never empty AAD).\n const wrap = chacha20Poly1305Encrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK,\n plaintext: args.cek,\n });\n if (wrap.length !== WRAP_LENGTH) {\n throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);\n }\n return { epk, wrap };\n}\n\n// Wrap the CEK for one hybrid recipient: X-Wing encapsulation → HKDF → AEAD.\n// The KEK info label doubles as the wrap AEAD AAD, mirroring the classical path.\nfunction wrapSlotMlkem768X25519(args: {\n pubR: Uint8Array;\n eseed: Uint8Array | undefined;\n cek: Uint8Array;\n nonce: Uint8Array;\n}): Mlkem768X25519Slot {\n const { enc, ss } = mlkem768x25519Encapsulate({\n publicKey: args.pubR,\n ...(args.eseed !== undefined ? { eseed: args.eseed } : {}),\n });\n if (enc.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new Error(`internal: enc.length=${enc.length}, expected ${MLKEM768X25519_ENC_LENGTH}`);\n }\n // The hybrid KEK salt binds the envelope nonce, the slot's own X-Wing\n // ciphertext, and the recipient public key, mirroring the classical salt: the\n // ciphertext anchors the KEK to a slot-unique value and `pub_R` binds it to\n // the specific recipient. It is computed outside the KEM, over the slot's wire\n // bytes, so it holds X-Wing as a black-box KEM.\n const kek = hkdfSha256({\n ikm: ss,\n salt: xwingKekSalt({ nonce: args.nonce, kemCt: enc, pubR: args.pubR }),\n info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n length: 32,\n });\n const wrap = chacha20Poly1305Encrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n plaintext: args.cek,\n });\n if (wrap.length !== WRAP_LENGTH) {\n throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);\n }\n return { kem_ct: enc, wrap };\n}\n\nexport function eciesSealedPoeWrap(args: WrapArgs): SealedPoeOutput {\n const { plaintext, recipientPublicKeys } = args;\n const kem: SealedKem = args.kem ?? 'x25519';\n const n = recipientPublicKeys.length;\n\n // The hash-claim digest is computed before any KEM/AEAD work: an item without\n // a content hash cannot be sealed (the ciphertext is bound to the plaintext\n // only through that digest).\n const hashesHash = itemHashesHash(args.hashes);\n\n // There is no fixed upper bound on slot count; the producer SDK polices the\n // per-record byte budget. Only the lower bound is enforced here.\n if (n < 1) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_EMPTY',\n `recipientPublicKeys.length=${n} must be >= 1`,\n );\n }\n\n const expectedPubLen =\n kem === 'x25519' ? X25519_PUBLIC_KEY_LENGTH : MLKEM768X25519_PUBLIC_KEY_LENGTH;\n for (let i = 0; i < n; i++) {\n const pub = recipientPublicKeys[i];\n if (pub === undefined || pub.length !== expectedPubLen) {\n throw new EciesSealedPoeError(\n 'KEM_EPK_LENGTH_MISMATCH',\n `recipientPublicKeys[${i}] MUST be exactly ${expectedPubLen} bytes for kem='${kem}'`,\n );\n }\n }\n\n if (kem === 'x25519') {\n if (args.eseeds !== undefined) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n \"eseeds is an X-Wing (mlkem768x25519) override and MUST NOT be supplied for kem='x25519'\",\n );\n }\n if (args.ephemeralSecrets !== undefined && args.ephemeralSecrets.length !== n) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n `ephemeralSecrets.length=${args.ephemeralSecrets.length} must match recipientPublicKeys.length=${n}`,\n );\n }\n } else {\n if (args.ephemeralSecrets !== undefined) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n \"ephemeralSecrets is an X25519 override and MUST NOT be supplied for kem='mlkem768x25519'\",\n );\n }\n if (args.eseeds !== undefined) {\n if (args.eseeds.length !== n) {\n throw new EciesSealedPoeError(\n 'EPHEMERAL_SECRETS_COUNT_MISMATCH',\n `eseeds.length=${args.eseeds.length} must match recipientPublicKeys.length=${n}`,\n );\n }\n for (let i = 0; i < n; i++) {\n const eseed = args.eseeds[i]!;\n if (eseed.length !== MLKEM768X25519_ESEED_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_EPHEMERAL_SECRET_LENGTH',\n `eseeds[${i}] MUST be exactly ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${eseed.length}`,\n );\n }\n }\n }\n }\n\n const cek = args.cek ?? randomBytes(CEK_LENGTH);\n const nonce = args.nonce ?? randomBytes(NONCE_LENGTH);\n if (cek.length !== CEK_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_CEK_LENGTH',\n `cek MUST be exactly ${CEK_LENGTH} bytes, got ${cek.length}`,\n );\n }\n if (nonce.length !== NONCE_LENGTH) {\n throw new EciesSealedPoeError(\n 'NONCE_LENGTH_MISMATCH',\n `nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${nonce.length}`,\n );\n }\n\n let envelope: SealedEnvelope;\n if (kem === 'x25519') {\n const slots: X25519Slot[] = [];\n for (let i = 0; i < n; i++) {\n slots.push(\n wrapSlotX25519({\n pubR: recipientPublicKeys[i]!,\n privEph: args.ephemeralSecrets ? (args.ephemeralSecrets[i] as Uint8Array) : undefined,\n cek,\n nonce,\n slotIdx: i,\n }),\n );\n }\n // Anonymity invariant (see csprngShuffle comment). The transcript is built\n // AFTER the shuffle so the MAC binds the on-wire slot order.\n if (args.skipShuffle !== true) {\n csprngShuffle(slots);\n }\n const slotsHash = computeSlotsHash({\n aead: SEALED_POE_AEAD,\n kem: 'x25519',\n nonce,\n slots,\n hashesHash,\n });\n envelope = {\n scheme: 1,\n aead: SEALED_POE_AEAD,\n kem: 'x25519',\n nonce,\n slots,\n slots_mac: sizedSlotsMac(cek, slotsHash),\n };\n } else {\n const slots: Mlkem768X25519Slot[] = [];\n for (let i = 0; i < n; i++) {\n slots.push(\n wrapSlotMlkem768X25519({\n pubR: recipientPublicKeys[i]!,\n eseed: args.eseeds ? (args.eseeds[i] as Uint8Array) : undefined,\n cek,\n nonce,\n }),\n );\n }\n if (args.skipShuffle !== true) {\n csprngShuffle(slots);\n }\n const slotsHash = computeSlotsHash({\n aead: SEALED_POE_AEAD,\n kem: 'mlkem768x25519',\n nonce,\n slots,\n hashesHash,\n });\n envelope = {\n scheme: 1,\n aead: SEALED_POE_AEAD,\n kem: 'mlkem768x25519',\n nonce,\n slots,\n slots_mac: sizedSlotsMac(cek, slotsHash),\n };\n }\n\n // Content is encrypted under a derived `payload_key` (a separate HKDF leaf of\n // the CEK salted by the envelope-unique nonce), never under the CEK directly,\n // in the segmented STREAM format. There is no content AAD: the content binds\n // to the header transitively — payload_key derives from the CEK, and the CEK\n // is committed to the full header (including hashes_hash) by slots_mac.\n const ciphertext = streamSeal({\n payloadKey: slotsPayloadKey({ cek, nonce }),\n plaintext,\n });\n\n return { envelope, ciphertext };\n}\n\nfunction sizedSlotsMac(cek: Uint8Array, slotsHash: Uint8Array): Uint8Array {\n const slotsMac = computeSlotsMac({ cek, slotsHash });\n if (slotsMac.length !== SLOTS_MAC_LENGTH) {\n throw new Error(`internal: slots_mac.length=${slotsMac.length}, expected ${SLOTS_MAC_LENGTH}`);\n }\n return slotsMac;\n}\n","// Isomorphic constant-time byte-equality. crypto-core is browser-safe by\n// design, so we cannot import `node:crypto.timingSafeEqual` — webpack rejects\n// the `node:` scheme in the browser bundle. A pure-JS XOR loop is constant-time\n// for equal-length inputs; length mismatch is a deliberate early-return (the\n// API surface itself leaks length, same as node's timingSafeEqual which throws).\nexport function compareCt(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n // Lengths are equal and `i` stays in-bounds, so both indexes are always\n // defined — no nullish guard is needed (and one would read as a guard for\n // an impossible case).\n for (let i = 0; i < a.length; i++) diff |= (a[i] as number) ^ (b[i] as number);\n return diff === 0;\n}\n","// Per-slot acceptance accumulator for the trial-decrypt loop.\n//\n// A slot is \"mine\" only when its KEM validity bit, its wrap-open, AND its\n// slot-set MAC check all hold (the folded per-slot `ok` bit). The accumulator\n// selects the FIRST accepted slot's CEK, keeps scanning every remaining slot\n// (the loop never breaks early within one private key's pass), and raises the\n// conflict bit when a later accepted slot recovers a CEK that differs from the\n// selected one — the multi-key commitment collision the construction fails\n// closed on. Slots that wrap-open under an attacker-chosen CEK but fail the\n// MAC are simply not accepted: they neither select a CEK nor raise a conflict,\n// so an honest slot later in the array still wins.\n//\n// The fold is branchless mask-based selection — no control flow keyed on which\n// slot matched:\n//\n// first = ok AND NOT found\n// cek_conflict = cek_conflict OR (ok AND found AND NOT ctEq(cand, selected))\n// selected_CEK = select(first, cand, selected) (byte masks 0x00/0xFF)\n// selected_idx = select(first, idx, selected_idx) (word masks 0/-1)\n// found = found OR ok\n//\n// Every update runs on every slot with the same operations; the state is a\n// fixed-size buffer plus 0|1 bits, never a data-dependent assignment guarded\n// by `if`. JavaScript offers no hardware constant-time guarantee — a JIT may\n// reintroduce data-dependent paths — so this is the best-effort discipline,\n// not a timing proof.\n//\n// Two accepted slots recovering DIFFERENT CEKs requires a collision in the\n// CEK-keyed commitment, so the conflict bit is not reachable through any\n// envelope the public API can build; it is exercised directly on this\n// accumulator. This module is internal to the trial-decrypt implementation and\n// is not part of the package surface.\n\nconst CEK_LENGTH = 32;\n\n// Mutable accumulator state. `foundBit` / `conflictBit` are 0|1 integers;\n// `selectedCek` is a fixed 32-byte buffer (all-zero until a slot is accepted);\n// `selectedSlotIdx` keeps the -1 sentinel until the first acceptance.\nexport interface SlotAcceptanceState {\n foundBit: number;\n conflictBit: number;\n readonly selectedCek: Uint8Array;\n selectedSlotIdx: number;\n}\n\nexport function newSlotAcceptanceState(): SlotAcceptanceState {\n return {\n foundBit: 0,\n conflictBit: 0,\n selectedCek: new Uint8Array(CEK_LENGTH),\n selectedSlotIdx: -1,\n };\n}\n\n// Fold one slot's outcome into the state. `ok` MUST be the slot's\n// `kem_ok AND open_ok AND mac_ok` acceptance as a 0|1 integer; `candidateCek`\n// MUST be exactly 32 bytes (the recovered CEK, or the caller's fixed dummy\n// when the wrap-open failed, so every slot folds the same-shaped input).\nexport function foldSlotAcceptance(\n state: SlotAcceptanceState,\n ok: number,\n candidateCek: Uint8Array,\n slotIdx: number,\n): void {\n if (candidateCek.length !== CEK_LENGTH) {\n // Structural programmer-error guard on a public quantity (the wrap length\n // is wire-validated upstream); never reachable from envelope data.\n throw new Error(\n `candidate CEK MUST be exactly ${CEK_LENGTH} bytes, got ${candidateCek.length}`,\n );\n }\n const okBit = ok & 1;\n const firstBit = okBit & (state.foundBit ^ 1);\n const firstByteMask = -firstBit & 0xff; // 0x00 or 0xFF\n const firstWordMask = -firstBit | 0; // 0 or -1 (all-ones int32)\n\n // Constant-time inequality of candidate vs selected as a 0|1 bit. Computed\n // unconditionally on every slot; its conflict contribution is masked off\n // unless this slot AND an earlier slot were both accepted.\n let diff = 0;\n for (let i = 0; i < CEK_LENGTH; i++) {\n diff |= (candidateCek[i] as number) ^ (state.selectedCek[i] as number);\n }\n const neqBit = ((diff | -diff) >>> 31) & 1;\n\n state.conflictBit |= okBit & state.foundBit & neqBit;\n for (let i = 0; i < CEK_LENGTH; i++) {\n state.selectedCek[i] =\n ((candidateCek[i] as number) & firstByteMask) |\n ((state.selectedCek[i] as number) & ~firstByteMask & 0xff);\n }\n state.selectedSlotIdx = (slotIdx & firstWordMask) | (state.selectedSlotIdx & ~firstWordMask);\n state.foundBit |= okBit;\n}\n\n// The pass outcome in consumer shape, read once after the whole slot loop.\nexport interface SlotAcceptanceOutcome {\n readonly found: boolean;\n readonly cekConflict: boolean;\n // The first accepted slot's CEK (null when nothing was accepted).\n readonly selectedCek: Uint8Array | null;\n // The first accepted slot's index (-1 when nothing was accepted).\n readonly selectedSlotIdx: number;\n}\n\nexport function finishSlotAcceptance(state: SlotAcceptanceState): SlotAcceptanceOutcome {\n const found = state.foundBit === 1;\n return {\n found,\n cekConflict: state.conflictBit === 1,\n selectedCek: found ? state.selectedCek : null,\n selectedSlotIdx: state.selectedSlotIdx,\n };\n}\n","// Multi-recipient sealed-PoE unwrap (age-style trial-decrypt with the slot-set\n// MAC folded into per-slot acceptance + partitioning-oracle length pre-checks).\n//\n// Three key forms (mutually exclusive — exactly one MUST be supplied):\n//\n// • Single-priv form: `recipientSecretKey: Uint8Array` — the standalone-verifier\n// path. Runs the trial-decrypt loop over `envelope.slots` once.\n//\n// • Multi-priv form: `recipientSecretKeys: ReadonlyArray<Uint8Array>` — for the\n// trial-decrypt scan of a rotated identity holding `[currentPriv, ...archivedPrivs]`.\n// Caller supplies the order; the iterator runs outer-loop = privkey ×\n// inner-loop = slot, short-circuiting on the first priv that accepts a\n// slot. The recommended caller order is `[currentPriv,\n// ...previousPrivsReversed]` (newest archive first).\n//\n// • Bundle form: `recipientKeyBundle` — both KEMs' secret lists; the dispatch\n// picks the right one from `envelope.kem`.\n//\n// The inner per-slot loop is constant-time across slots: every slot of a key's\n// pass is entered regardless of match position, and every slot pays the same\n// KEM + HKDF + wrap-open + MAC work, so an observer cannot infer which slot\n// index matched. The outer loop short-circuits on the first cross-priv match —\n// that channel leaks only the weak \"which key matched\" ordering signal,\n// intrinsic to multi-key trial-decrypt.\n//\n// Per-slot acceptance folds three bits: `ok = kem_ok AND open_ok AND mac_ok`.\n// The MAC fold is load-bearing: a malicious sender can craft a slot that\n// wrap-opens under a recipient's key with an attacker-chosen CEK, but that CEK\n// does not reproduce `slots_mac`, so the forged slot is skipped exactly like a\n// non-matching one and an honest slot later in the array still wins.\n//\n// The per-slot recovery body differs by KEM, but both take the same work\n// shape — KEK derivation, then a wrap-open attempt on EVERY slot:\n// • x25519: X25519 ECDH → HKDF → AEAD-unwrap; a low-order epk\n// (RFC 7748 §6.1 contributory-check rejection) sets\n// kem_ok=false, derives a dummy KEK instead, and STILL\n// attempts the wrap-open under it, so an invalid-ECDH slot\n// pays the identical per-slot cost and can never be\n// accepted (the kem bit is folded into acceptance).\n// • mlkem768x25519: X-Wing decapsulate → HKDF → AEAD-unwrap; NEVER throws on\n// attacker wire data (ML-KEM implicit rejection yields a\n// pseudorandom shared secret), so no try/catch around it.\n\nimport { chacha20Poly1305Decrypt } from '../aead/chacha20-poly1305';\nimport { AeadVerificationError } from '../aead/errors';\nimport { hkdfSha256 } from '../kdf/hkdf';\nimport {\n mlkem768x25519Decapsulate,\n mlkem768x25519Keygen,\n MLKEM768X25519_ENC_LENGTH,\n} from '../kem/mlkem768x25519';\nimport { x25519Ecdh, X25519LowOrderPointError, x25519PublicKey } from '../kem/x25519';\nimport { compareCt } from '../util/compare-ct';\n\nimport { EciesSealedPoeError } from './errors';\nimport {\n finishSlotAcceptance,\n foldSlotAcceptance,\n newSlotAcceptanceState,\n} from './slot-acceptance';\nimport { streamOpen, StreamTamperedError } from './stream';\nimport {\n computeSlotsHash,\n computeSlotsMac,\n itemHashesHash,\n MAX_DECODED_ENVELOPE_BYTES,\n MAX_SLOTS,\n slotsPayloadKey,\n x25519KekSalt,\n xwingKekSalt,\n type ItemHashes,\n} from './transcript';\nimport {\n CARDANO_POE_HKDF_INFO_KEK,\n CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n SEALED_POE_AEAD,\n type Mlkem768X25519Slot,\n type SealedEnvelope,\n type X25519Slot,\n} from './wrap';\n\n// Typed decryption outcomes — internal diagnostics for a trusted local caller.\n// An untrusted external caller MUST receive one indistinguishable generic\n// failure regardless of which of these fired.\nexport type UnwrapFailureReason = 'WRONG_RECIPIENT_KEY' | 'TAMPERED_HEADER' | 'TAMPERED_CIPHERTEXT';\n\nexport type UnwrapResult =\n | { readonly matched: true; readonly plaintext: Uint8Array }\n | { readonly matched: false; readonly reason: UnwrapFailureReason };\n\n// Unified recipient key bundle. Callers hold BOTH the X25519\n// private-key chain (current + archived, for classical and rotation history)\n// AND the X-Wing secret seed(s) (for the hybrid KEM), without knowing which a\n// given record was sealed under. They pass the whole bundle; the unwrap /\n// trial-decrypt dispatch selects the correct secret list from `envelope.kem`:\n//\n// • kem === 'x25519' → bundle.x25519PrivateKeys\n// • kem === 'mlkem768x25519' → bundle.mlkem768x25519SecretSeeds\n//\n// Both lists are ordered newest-first (caller's responsibility — the outer\n// trial-decrypt loop scans them in order). A list MAY be empty when the\n// recipient holds no key for that KEM (e.g. archived-only X25519 identities\n// predate the hybrid KEM, so their hybrid seed list is empty); a bundle whose\n// selected list is empty unwraps to a clean no-match without touching any KEM\n// primitive.\nexport interface RecipientKeyBundle {\n readonly x25519PrivateKeys: ReadonlyArray<Uint8Array>;\n readonly mlkem768x25519SecretSeeds: ReadonlyArray<Uint8Array>;\n}\n\n// Select the secret-key list a bundle contributes for the given envelope KEM.\n// The single dispatch seam — unwrap and trial-decrypt both route through here so\n// the per-KEM selection lives in exactly one place.\nfunction selectBundleSecrets(\n envelope: SealedEnvelope,\n bundle: RecipientKeyBundle,\n): ReadonlyArray<Uint8Array> {\n return envelope.kem === 'x25519' ? bundle.x25519PrivateKeys : bundle.mlkem768x25519SecretSeeds;\n}\n\ninterface UnwrapArgsCommon {\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n // The item's plaintext-hash claim, as carried in the record body. Bound into\n // the slots transcript: an envelope spliced onto an item with a different\n // hashes map fails the per-slot MAC, before any content work.\n readonly hashes: ItemHashes;\n // Test-only instrumentation for the constant-time-across-slots invariant.\n // The unwrap fn bumps `count` once per inner-loop iteration entered. In the\n // multi-priv path, `count` is reset at the start of each outer iteration and\n // — when `perPrivCounts` is provided — the final per-priv inner count is\n // appended after that priv's inner loop completes. Production callers never\n // pass this.\n readonly _slotsAttemptedOut?: { count: number; perPrivCounts?: number[] };\n // Test-only multi-priv outer-loop iteration counter. Bumped to `k + 1` at\n // the start of each outer-loop iteration. Production callers never pass this.\n readonly _privsAttemptedOut?: { count: number };\n}\n\nexport interface UnwrapArgsSinglePriv extends UnwrapArgsCommon {\n readonly recipientSecretKey: Uint8Array;\n}\n\nexport interface UnwrapArgsMultiPriv extends UnwrapArgsCommon {\n readonly recipientSecretKeys: ReadonlyArray<Uint8Array>;\n}\n\n// Bundle form of the multi-priv path: the caller passes both KEMs' secret\n// lists and the dispatch picks the right one from `envelope.kem`. This is the\n// surface every read-path consumer (inbox decrypt, CLI decrypt, standalone\n// recipient verifier) should use — they hold the whole identity key bundle and\n// must NOT pre-select a list or rebuild slots themselves.\nexport interface UnwrapArgsBundle extends UnwrapArgsCommon {\n readonly recipientKeyBundle: RecipientKeyBundle;\n}\n\nexport type UnwrapArgs = UnwrapArgsSinglePriv | UnwrapArgsMultiPriv | UnwrapArgsBundle;\n\n// Trial-decrypt-only sibling of eciesSealedPoeUnwrap. Runs the per-slot\n// acceptance (KEM + wrap-open + slots_mac) but NEVER opens the content stream\n// (which requires the off-chain ciphertext blob, not available at trial-decrypt\n// time). Used by an inbox-scan agent to discover readable records before\n// fetching their ciphertext.\ninterface TrialDecryptOnlyArgsCommon {\n readonly envelope: SealedEnvelope;\n readonly hashes: ItemHashes;\n readonly _slotsAttemptedOut?: { count: number; perPrivCounts?: number[] };\n readonly _privsAttemptedOut?: { count: number };\n}\n\n// Exactly one of `recipientSecretKeys` (flat, KEM-pre-selected) or\n// `recipientKeyBundle` (whole bundle, KEM dispatched from `envelope.kem`).\n// Inbox-scan consumers pass the bundle; the low-level / parity tests pass the\n// flat list directly.\nexport type TrialDecryptOnlyArgs = TrialDecryptOnlyArgsCommon &\n (\n | { readonly recipientSecretKeys: ReadonlyArray<Uint8Array> }\n | { readonly recipientKeyBundle: RecipientKeyBundle }\n );\n\n// Binary by design: with the MAC folded into per-slot acceptance there is no\n// observable middle state — a slot either fully matches (KEM + wrap + MAC) or\n// it does not. A CEK conflict among accepted slots fails closed to no_match.\nexport type TrialDecryptOnlyResult =\n | { readonly kind: 'match'; readonly slotIdx: number; readonly cek: Uint8Array }\n | { readonly kind: 'no_match' };\n\nconst ZERO_NONCE_12: Uint8Array = new Uint8Array(12);\nconst CEK_LENGTH = 32 as const;\nconst X25519_SECRET_KEY_LENGTH = 32 as const;\nconst X25519_PUBLIC_KEY_LENGTH = 32 as const;\nconst NONCE_LENGTH = 24 as const;\nconst WRAP_LENGTH = 48 as const;\nconst SLOTS_MAC_LENGTH = 32 as const;\n\n// Stable string key for a byte string, used only for the per-slot KEM-material\n// duplicate check (a structural pre-trial gate, not a constant-time comparison).\nfunction bytesKey(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) {\n s += String.fromCharCode(bytes[i]!);\n }\n return s;\n}\n\n// Partitioning-oracle defence: every wire\n// length MUST be validated before any KEM/AEAD primitive is invoked, so malformed\n// records cannot probe per-slot failure ordering. Shared between\n// `eciesSealedPoeUnwrap` (single- and multi-priv) and `eciesSealedPoeTrialDecrypt`\n// to guarantee byte-identical pre-trial behaviour and to keep the dispatch\n// invariant in one place.\nfunction assertEnvelopeStructure(\n envelope: SealedEnvelope,\n multiPrivKeys?: ReadonlyArray<Uint8Array>,\n singlePrivKey?: Uint8Array,\n): void {\n if (envelope.scheme !== 1) {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_ENVELOPE_SCHEME',\n `envelope.scheme=${String(envelope.scheme)} unsupported (expected 1)`,\n );\n }\n if (envelope.aead !== SEALED_POE_AEAD) {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_AEAD_ALG',\n `envelope.aead=${String(envelope.aead)} unsupported (expected '${SEALED_POE_AEAD}')`,\n );\n }\n if (envelope.kem !== 'x25519' && envelope.kem !== 'mlkem768x25519') {\n throw new EciesSealedPoeError(\n 'UNSUPPORTED_KEM_ALG',\n `envelope.kem=${String((envelope as { kem: string }).kem)} unsupported (expected 'x25519' or 'mlkem768x25519')`,\n );\n }\n\n // Envelope-level length pre-checks in this exact order.\n const n = envelope.slots.length;\n if (n < 1) {\n throw new EciesSealedPoeError('ENC_SLOTS_EMPTY', `envelope.slots.length=${n} must be >= 1`);\n }\n // Resource bound: reject an envelope with more than MAX_SLOTS slots before any\n // KEM/AEAD primitive runs, so a malformed record cannot drive unbounded\n // per-slot work. Checked before the per-slot length loop below.\n if (n > MAX_SLOTS) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_TOO_MANY',\n `envelope.slots.length=${n} exceeds MAX_SLOTS=${MAX_SLOTS}`,\n );\n }\n if (envelope.nonce.length !== NONCE_LENGTH) {\n throw new EciesSealedPoeError(\n 'NONCE_LENGTH_MISMATCH',\n `envelope.nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${envelope.nonce.length}`,\n );\n }\n if (envelope.slots_mac.length !== SLOTS_MAC_LENGTH) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_MAC_INVALID_LENGTH',\n `envelope.slots_mac MUST be exactly ${SLOTS_MAC_LENGTH} bytes, got ${envelope.slots_mac.length}`,\n );\n }\n\n // Per-slot length pre-checks — KEM-driven. ALL slots are validated here,\n // before any decapsulation, so the trial-decrypt loop never observes a\n // malformed slot (partitioning-oracle-safe ordering).\n //\n // Per-slot KEK uniqueness is also enforced here. The zero-nonce per-slot wrap\n // is safe only because each slot draws fresh KEM randomness, so its KEK is\n // unique; two slots sharing the same KEM material derive the same KEK and\n // repeat a (KEK, zero-nonce) pair. The KEM material that fixes the KEK is the\n // `epk` (x25519) or the `kem_ct` (hybrid) — both bound into the KEK salt — so\n // a repeat of either across slots is rejected outright.\n const seenKemMaterial = new Set<string>();\n if (envelope.kem === 'x25519') {\n for (let i = 0; i < n; i++) {\n const slot = envelope.slots[i]!;\n if (slot.epk.length !== X25519_PUBLIC_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'KEM_EPK_LENGTH_MISMATCH',\n `envelope.slots[${i}].epk MUST be exactly ${X25519_PUBLIC_KEY_LENGTH} bytes, got ${slot.epk.length}`,\n );\n }\n if (slot.wrap.length !== WRAP_LENGTH) {\n throw new EciesSealedPoeError(\n 'WRAP_LENGTH_MISMATCH',\n `envelope.slots[${i}].wrap MUST be exactly ${WRAP_LENGTH} bytes, got ${slot.wrap.length}`,\n );\n }\n const key = bytesKey(slot.epk);\n if (seenKemMaterial.has(key)) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL',\n `envelope.slots[${i}].epk duplicates an earlier slot — per-slot KEK uniqueness is violated`,\n );\n }\n seenKemMaterial.add(key);\n }\n } else {\n for (let i = 0; i < n; i++) {\n const slot = envelope.slots[i]!;\n if (slot.kem_ct.length !== MLKEM768X25519_ENC_LENGTH) {\n throw new EciesSealedPoeError(\n 'KEM_CT_LENGTH_MISMATCH',\n `envelope.slots[${i}].kem_ct MUST be exactly ${MLKEM768X25519_ENC_LENGTH} bytes, got ${slot.kem_ct.length}`,\n );\n }\n if (slot.wrap.length !== WRAP_LENGTH) {\n throw new EciesSealedPoeError(\n 'WRAP_LENGTH_MISMATCH',\n `envelope.slots[${i}].wrap MUST be exactly ${WRAP_LENGTH} bytes, got ${slot.wrap.length}`,\n );\n }\n const key = bytesKey(slot.kem_ct);\n if (seenKemMaterial.has(key)) {\n throw new EciesSealedPoeError(\n 'ENC_SLOTS_DUPLICATE_KEM_MATERIAL',\n `envelope.slots[${i}].kem_ct duplicates an earlier slot — per-slot KEK uniqueness is violated`,\n );\n }\n seenKemMaterial.add(key);\n }\n }\n\n // Decoded-envelope byte backstop. Every per-slot field above is validated to a\n // fixed length, so the decoded envelope's aggregate size is determined here:\n // nonce + slots_mac + per-slot (epk|kem_ct + wrap). Reject before any KEM/AEAD\n // primitive when it exceeds the bound — a tighter resource cap than MAX_SLOTS\n // for honest records, and the bound a parser that can see the decoded size\n // enforces. (The slot-count cap above already bounds work; this is the byte\n // backstop the verifier also pins.)\n const perSlotBytes =\n envelope.kem === 'x25519'\n ? X25519_PUBLIC_KEY_LENGTH + WRAP_LENGTH\n : MLKEM768X25519_ENC_LENGTH + WRAP_LENGTH;\n const decodedEnvelopeBytes = NONCE_LENGTH + SLOTS_MAC_LENGTH + n * perSlotBytes;\n if (decodedEnvelopeBytes > MAX_DECODED_ENVELOPE_BYTES) {\n throw new EciesSealedPoeError(\n 'ENC_ENVELOPE_TOO_LARGE',\n `decoded envelope size ${decodedEnvelopeBytes} exceeds MAX_DECODED_ENVELOPE_BYTES=${MAX_DECODED_ENVELOPE_BYTES}`,\n );\n }\n\n if (multiPrivKeys !== undefined) {\n for (let i = 0; i < multiPrivKeys.length; i++) {\n if (multiPrivKeys[i]!.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n `recipientSecretKeys[${i}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${multiPrivKeys[i]!.length}`,\n );\n }\n }\n } else if (singlePrivKey !== undefined) {\n if (singlePrivKey.length !== X25519_SECRET_KEY_LENGTH) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n `recipientSecretKey MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${singlePrivKey.length}`,\n );\n }\n }\n}\n\n// All-zero IKM for the dummy KEK an invalid-ECDH slot derives so it pays the\n// same HKDF work as a live slot (see `tryX25519Slot`).\nconst ZERO_IKM_32: Uint8Array = new Uint8Array(32);\n// Fixed dummy candidate CEK for a slot whose wrap-open failed, so the per-slot\n// MAC step runs uniformly on every slot. The dummy is independent of the failed\n// ciphertext, and its MAC outcome can never accept a slot — acceptance also\n// requires the slot's `ok` bit.\nconst DUMMY_CEK_32: Uint8Array = new Uint8Array(32);\n\n// One slot's recovery outcome: the folded `kem_ok AND open_ok` acceptance\n// contribution as a 0|1 integer, plus the candidate CEK — the recovered\n// 32-byte wrap plaintext, or the fixed dummy when the bit is 0 — so the\n// caller's MAC step folds the same-shaped input for every slot.\ninterface SlotCandidate {\n readonly ok: number;\n readonly candidate: Uint8Array;\n}\n\n// Attempt the per-slot wrap AEAD, or yield the dummy candidate. Atomic: on a\n// tag failure no plaintext escapes and the candidate is the fixed all-zero\n// dummy, independent of the failed ciphertext.\nfunction wrapOpenOrDummy(kek: Uint8Array, aad: Uint8Array, wrap: Uint8Array): SlotCandidate {\n try {\n const plaintext = chacha20Poly1305Decrypt({\n key: kek,\n nonce: ZERO_NONCE_12,\n aad,\n ciphertext: wrap,\n });\n // The wrap is pre-validated to 48 bytes, so the recovered CEK is exactly\n // 32; anything else is treated as a failed open.\n if (plaintext.length === CEK_LENGTH) {\n return { ok: 1, candidate: plaintext };\n }\n return { ok: 0, candidate: DUMMY_CEK_32 };\n } catch (e) {\n if (!(e instanceof AeadVerificationError)) throw e;\n return { ok: 0, candidate: DUMMY_CEK_32 };\n }\n}\n\n// Classical (x25519) per-slot recovery body. The wrap AEAD is attempted on\n// EVERY slot (no match-position-dependent skip), so a per-priv scan recovers a\n// candidate CEK from each slot the recipient is addressed in — which is what\n// the CEK-conflict detection needs — and every slot pays the identical\n// ECDH + HKDF + AEAD-open cost regardless of where the match lands.\n//\n// `kem_ok` is the X25519 validity bit: a small-order `epk` drives the shared\n// secret to all-zero, which RFC 7748 §6.1 rejects. @noble/curves signals this\n// by THROWING from `getSharedSecret`, so a fully branchless ct-select over the\n// shared secret is not expressible against this library API. The next-best,\n// equivalent form is taken instead: on the all-zero rejection the slot derives\n// a DUMMY KEK from `ikm=0^32` (same salt/info — same HKDF work) and STILL\n// attempts the wrap-open under it, so the invalid-ECDH slot takes the same\n// per-slot work shape as a live one, while `kem_ok=0` folded into the returned\n// bit means it can never be accepted regardless of the AEAD outcome.\nfunction tryX25519Slot(args: {\n slot: X25519Slot;\n nonce: Uint8Array;\n recipientSecretKey: Uint8Array;\n pubRLocal: Uint8Array;\n}): SlotCandidate {\n const salt = x25519KekSalt({ nonce: args.nonce, epk: args.slot.epk, pubR: args.pubRLocal });\n let kemOk = 1;\n let kek: Uint8Array;\n try {\n const shared = x25519Ecdh({\n secretKey: args.recipientSecretKey,\n theirPublicKey: args.slot.epk,\n });\n kek = hkdfSha256({ ikm: shared, salt, info: CARDANO_POE_HKDF_INFO_KEK, length: 32 });\n } catch (e) {\n if (!(e instanceof X25519LowOrderPointError)) throw e;\n kemOk = 0;\n kek = hkdfSha256({ ikm: ZERO_IKM_32, salt, info: CARDANO_POE_HKDF_INFO_KEK, length: 32 });\n }\n const opened = wrapOpenOrDummy(kek, CARDANO_POE_HKDF_INFO_KEK, args.slot.wrap);\n return { ok: kemOk & opened.ok, candidate: opened.candidate };\n}\n\n// Hybrid (mlkem768x25519) per-slot recovery body. X-Wing decapsulate NEVER\n// throws on attacker wire data (ML-KEM implicit rejection), so there is no\n// try/catch and the KEM validity bit is constant 1: a wrong shared secret\n// simply yields a KEK that fails the AEAD tag. As in the classical body, the\n// AEAD is attempted on EVERY slot (full decapsulate + HKDF + AEAD-open) so\n// matching and non-matching slots cost the same X-Wing work.\nfunction tryMlkem768X25519Slot(args: {\n slot: Mlkem768X25519Slot;\n nonce: Uint8Array;\n recipientSecretKey: Uint8Array;\n pubR: Uint8Array;\n}): SlotCandidate {\n // kem_ct length was validated against MLKEM768X25519_ENC_LENGTH in\n // assertEnvelopeStructure, so this decapsulate is constant-work.\n const ss = mlkem768x25519Decapsulate({\n secretSeed: args.recipientSecretKey,\n enc: args.slot.kem_ct,\n });\n // The KEK salt binds the envelope nonce, the slot's own ciphertext, and the\n // recipient's own X-Wing public key (recomputed from the held seed), exactly\n // as the producer bound them — see the wrap path.\n const kek = hkdfSha256({\n ikm: ss,\n salt: xwingKekSalt({ nonce: args.nonce, kemCt: args.slot.kem_ct, pubR: args.pubR }),\n info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,\n length: 32,\n });\n return wrapOpenOrDummy(kek, CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519, args.slot.wrap);\n}\n\n// Outcome of one private key's full pass over the slot array.\n//\n// • found — some slot fully matched (kem_ok AND open_ok AND mac_ok).\n// • selectedCek — the FIRST matching slot's CEK (null when !found).\n// • cekConflict — two matching slots recovered different CEKs (the\n// commitment collision the construction fails closed on).\n// • anyOpened — some slot wrap-opened under a valid KEM (`kem_ok AND\n// open_ok`), regardless of its MAC outcome. Distinguishes\n// the tampered-header diagnostic from a plain non-recipient.\ninterface PrivPassResult {\n readonly found: boolean;\n readonly selectedCek: Uint8Array | null;\n readonly selectedSlotIdx: number;\n readonly cekConflict: boolean;\n readonly anyOpened: boolean;\n}\n\n// Per-priv inner trial-decrypt loop, KEM-driven, with the slot-set MAC folded\n// into per-slot acceptance. Every slot is entered and every slot pays the same\n// work: KEM recovery, wrap-open, then the MAC check over the loop-constant\n// `slots_hash` — keyed from the recovered candidate CEK, or from a fixed dummy\n// when the wrap-open failed, so the MAC step is uniform too. This follows the\n// spec loop shape:\n//\n// ok = kem_ok AND open_ok AND mac_ok\n// first = ok AND NOT found\n// cek_conflict = cek_conflict OR (ok AND found AND NOT ctEq(cand, selected))\n// selected_CEK = select(first, cand, selected)\n// found = found OR ok\n//\n// No early break is taken, the bits combine with integer `&`/`|` (never a\n// short-circuit), and the running selection state is folded with mask-based\n// updates, so the scan takes the same source-level path across the whole slot\n// set regardless of where (or whether) a match lands.\nfunction runPrivPass(\n envelope: SealedEnvelope,\n recipientSecretKey: Uint8Array,\n slotsHash: Uint8Array,\n slotsAttemptedOut: { count: number; perPrivCounts?: number[] } | undefined,\n): PrivPassResult {\n const n = envelope.slots.length;\n const state = newSlotAcceptanceState();\n let anyOpenedBit = 0;\n\n const acceptSlot = (slot: SlotCandidate, i: number): void => {\n anyOpenedBit |= slot.ok;\n const macOk =\n Number(compareCt(computeSlotsMac({ cek: slot.candidate, slotsHash }), envelope.slots_mac)) &\n 1;\n foldSlotAcceptance(state, slot.ok & macOk, slot.candidate, i);\n };\n\n if (envelope.kem === 'x25519') {\n const pubRLocal = x25519PublicKey({ secretKey: recipientSecretKey });\n for (let i = 0; i < n; i++) {\n if (slotsAttemptedOut !== undefined) {\n slotsAttemptedOut.count = i + 1;\n }\n acceptSlot(\n tryX25519Slot({\n slot: envelope.slots[i]!,\n nonce: envelope.nonce,\n recipientSecretKey,\n pubRLocal,\n }),\n i,\n );\n }\n } else {\n // Recompute the recipient's own X-Wing public key from the held seed: the\n // hybrid KEK salt binds `pub_R`, so each private key in a multi-key scan\n // MUST re-derive it (a single shared pub_R would compute the wrong KEK for\n // every key but one).\n const pubR = mlkem768x25519Keygen(recipientSecretKey).publicKey;\n for (let i = 0; i < n; i++) {\n if (slotsAttemptedOut !== undefined) {\n slotsAttemptedOut.count = i + 1;\n }\n acceptSlot(\n tryMlkem768X25519Slot({\n slot: envelope.slots[i]!,\n nonce: envelope.nonce,\n recipientSecretKey,\n pubR,\n }),\n i,\n );\n }\n }\n const outcome = finishSlotAcceptance(state);\n return {\n found: outcome.found,\n selectedCek: outcome.selectedCek,\n selectedSlotIdx: outcome.selectedSlotIdx,\n cekConflict: outcome.cekConflict,\n anyOpened: anyOpenedBit === 1,\n };\n}\n\n// 32-byte slots-transcript hash. It depends only on the header, the slots, and\n// the item's hash claim, so it is constant across the multi-priv outer loop and\n// the per-slot trial-decrypt loop — callers compute it ONCE and re-key the HMAC\n// from each candidate CEK over this same 32-byte message.\nfunction slotsHashBytes(envelope: SealedEnvelope, hashes: ItemHashes): Uint8Array {\n return computeSlotsHash({\n aead: envelope.aead,\n kem: envelope.kem,\n nonce: envelope.nonce,\n slots: envelope.slots as ReadonlyArray<X25519Slot | Mlkem768X25519Slot>,\n hashesHash: itemHashesHash(hashes),\n });\n}\n\nexport function eciesSealedPoeUnwrap(args: UnwrapArgs): UnwrapResult {\n const { envelope, ciphertext } = args;\n\n // Exactly-one-of validation across the three UnwrapArgs forms (single-priv,\n // flat multi-priv, bundle). Runs before any AEAD / wire-shape work so a\n // malformed call cannot probe per-slot AEAD timing. The bundle form resolves\n // to a flat multi-priv list here by dispatching on `envelope.kem` — from this\n // point the loop is identical regardless of how the caller supplied keys.\n const hasSingle = 'recipientSecretKey' in args;\n const hasBundle = 'recipientKeyBundle' in args;\n const multiPrivKeys: ReadonlyArray<Uint8Array> | undefined = hasBundle\n ? selectBundleSecrets(envelope, (args as UnwrapArgsBundle).recipientKeyBundle)\n : 'recipientSecretKeys' in args\n ? (args as UnwrapArgsMultiPriv).recipientSecretKeys\n : undefined;\n const hasMulti = multiPrivKeys !== undefined;\n if (hasSingle === hasMulti) {\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'exactly one of recipientSecretKey / recipientSecretKeys / recipientKeyBundle MUST be supplied',\n );\n }\n // A bundle selecting an empty list for this KEM means the recipient holds no\n // key of the matching kind (e.g. an archived-only identity facing a hybrid\n // record). That is a legitimate non-match, NOT a malformed call — return a\n // clean WRONG_RECIPIENT_KEY without invoking any KEM primitive. The flat\n // multi-priv form keeps the \"empty array is a programmer error\" contract.\n if (hasMulti && multiPrivKeys!.length === 0) {\n if (hasBundle) {\n return { matched: false, reason: 'WRONG_RECIPIENT_KEY' };\n }\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'recipientSecretKeys MUST be a non-empty array, got length=0',\n );\n }\n\n // Partitioning-oracle pre-checks; per-priv length validation happens\n // inside `assertEnvelopeStructure`.\n if (hasMulti) {\n assertEnvelopeStructure(envelope, multiPrivKeys, undefined);\n } else {\n assertEnvelopeStructure(envelope, undefined, (args as UnwrapArgsSinglePriv).recipientSecretKey);\n }\n\n // The slots-transcript hash (which also digests the item's hash claim) is\n // constant across the whole scan — compute it ONCE, then re-key the HMAC from\n // each candidate CEK over this same 32-byte message.\n const slotsHash = slotsHashBytes(envelope, args.hashes);\n\n let matchedCek: Uint8Array | null = null;\n let anyOpenedAcrossPrivs = false;\n\n const privKeys: ReadonlyArray<Uint8Array> = hasMulti\n ? multiPrivKeys!\n : [(args as UnwrapArgsSinglePriv).recipientSecretKey];\n\n for (let k = 0; k < privKeys.length; k++) {\n if (args._privsAttemptedOut !== undefined) {\n args._privsAttemptedOut.count = k + 1;\n }\n if (args._slotsAttemptedOut !== undefined) {\n args._slotsAttemptedOut.count = 0;\n }\n const pass = runPrivPass(envelope, privKeys[k]!, slotsHash, args._slotsAttemptedOut);\n if (args._slotsAttemptedOut?.perPrivCounts !== undefined) {\n args._slotsAttemptedOut.perPrivCounts.push(args._slotsAttemptedOut.count);\n }\n anyOpenedAcrossPrivs = anyOpenedAcrossPrivs || pass.anyOpened;\n if (!pass.found) continue;\n // Two accepted slots recovering different CEKs is the commitment collision\n // the construction fails closed on — an anomalous slot set, surfaced as the\n // generic tampered-header diagnostic.\n if (pass.cekConflict) {\n return { matched: false, reason: 'TAMPERED_HEADER' };\n }\n matchedCek = pass.selectedCek;\n // The outer cross-priv loop short-circuits on the first priv that accepted\n // a slot. This intentionally leaks \"which priv matched\" → \"how many key\n // rotations the recipient has performed\". We accept it: trial-decrypt runs\n // client-side, so this timing is only locally observable, and the leak is a\n // weak ordering signal, not a key/plaintext oracle. Making the outer loop\n // constant-work would cost a FULL KEM pass (for the hybrid branch a full\n // X-Wing decapsulation per slot) for EVERY archived priv on EVERY record;\n // the benefit (hiding a count the user already knows) does not justify it.\n // The inner per-slot loop IS constant across slots.\n break;\n }\n\n if (matchedCek === null) {\n // A slot wrap-opened somewhere but nothing passed the folded acceptance:\n // some slot, header field, the hashes claim, or slots_mac itself was\n // tampered. No wrap-open at all is a plain non-recipient.\n return {\n matched: false,\n reason: anyOpenedAcrossPrivs ? 'TAMPERED_HEADER' : 'WRONG_RECIPIENT_KEY',\n };\n }\n\n // Content opens under the derived `payload_key` in the segmented STREAM\n // format; each chunk's tag is verified before its plaintext is released.\n try {\n const plaintext = streamOpen({\n payloadKey: slotsPayloadKey({ cek: matchedCek, nonce: envelope.nonce }),\n ciphertext,\n });\n return { matched: true, plaintext };\n } catch (e) {\n if (!(e instanceof StreamTamperedError)) throw e;\n return { matched: false, reason: 'TAMPERED_CIPHERTEXT' };\n }\n}\n\n// Trial-decrypt half of the sealed-PoE unwrap algorithm:\n// recovers the CEK + slot index without touching the content stream. Used by an\n// inbox-scan agent where the on-chain envelope is available but the off-chain\n// ciphertext blob is fetched lazily only when the user invokes Decrypt.\n//\n// Mirrors the multi-priv branch of `eciesSealedPoeUnwrap`: same\n// partitioning-oracle pre-checks, same per-priv inner loop with the MAC folded\n// into per-slot acceptance, same constant-across-slots invariant. Differs only\n// in the return shape: `{kind: 'match', slotIdx, cek}` instead of plaintext;\n// `{kind: 'no_match'}` for everything else (per-slot acceptance is binary, so\n// there is no distinguishable middle outcome). Cross-priv variable-time\n// short-circuit is preserved (leaks \"which priv matched\" → \"how many\n// rotations\", a documented weak ordering signal).\nexport function eciesSealedPoeTrialDecrypt(args: TrialDecryptOnlyArgs): TrialDecryptOnlyResult {\n const { envelope } = args;\n\n // Bundle form selects the per-KEM list from `envelope.kem`; flat form is\n // already KEM-pre-selected. An empty bundle list for this KEM is a clean\n // no_match (the recipient holds no key of the matching kind), whereas an\n // empty flat list stays a programmer error.\n const hasBundle = 'recipientKeyBundle' in args;\n const recipientSecretKeys: ReadonlyArray<Uint8Array> = hasBundle\n ? selectBundleSecrets(envelope, args.recipientKeyBundle)\n : args.recipientSecretKeys;\n\n if (recipientSecretKeys.length === 0) {\n if (hasBundle) {\n return { kind: 'no_match' };\n }\n throw new EciesSealedPoeError(\n 'INVALID_RECIPIENT_KEY',\n 'recipientSecretKeys MUST be a non-empty array, got length=0',\n );\n }\n assertEnvelopeStructure(envelope, recipientSecretKeys, undefined);\n\n const slotsHash = slotsHashBytes(envelope, args.hashes);\n\n for (let k = 0; k < recipientSecretKeys.length; k++) {\n if (args._privsAttemptedOut !== undefined) {\n args._privsAttemptedOut.count = k + 1;\n }\n if (args._slotsAttemptedOut !== undefined) {\n args._slotsAttemptedOut.count = 0;\n }\n const pass = runPrivPass(envelope, recipientSecretKeys[k]!, slotsHash, args._slotsAttemptedOut);\n if (args._slotsAttemptedOut?.perPrivCounts !== undefined) {\n args._slotsAttemptedOut.perPrivCounts.push(args._slotsAttemptedOut.count);\n }\n if (!pass.found) continue;\n // A CEK conflict is never a clean match — fail closed.\n if (pass.cekConflict) {\n return { kind: 'no_match' };\n }\n return {\n kind: 'match',\n slotIdx: pass.selectedSlotIdx,\n cek: pass.selectedCek as Uint8Array,\n };\n }\n return { kind: 'no_match' };\n}\n","// cardano-poe-pw-norm-v1: the normative passphrase normalization profile.\n//\n// Two implementations MUST derive a byte-identical CEK from the same\n// passphrase, so the normalization applied before Argon2id is pinned, in\n// order:\n//\n// 1. Bound the raw input (a pre-KDF denial-of-service backstop).\n// 2. NFKC under the pinned Unicode 16.0.0 tables. Input the pinned tables\n// cannot normalize stably — an unpaired surrogate, or a code point that\n// Unicode 16.0 leaves unassigned (a later Unicode version may give it a\n// decomposition and silently change the derived key) — is rejected.\n// 3. Collapse every maximal run of White_Space characters to one U+0020.\n// 4. Trim leading/trailing U+0020.\n// 5. Reject the empty result — a whitespace-only passphrase normalizes to\n// zero bytes, which Argon2id would silently accept, keying the record to\n// a CEK any party can derive.\n// 6. UTF-8-encode; those bytes are the Argon2id password input.\n//\n// Every Unicode-sensitive step resolves against the pinned Unicode 16.0.0\n// data — the NFKC tables and the White_Space property both — never the host\n// engine, whose tables float with its Unicode version.\n\nimport { Nfkc16Error, isWhiteSpace16, nfkc16 } from '../unicode/nfkc16';\nimport { EciesSealedPoeError } from './errors';\n\n// Reference bound on the RAW UTF-8 byte length of a passphrase, enforced before\n// any normalization or hashing work. A deployment-pinned constant, not a wire\n// field; deployments MAY tighten it.\nexport const MAX_PASSPHRASE_INPUT_BYTES = 4096;\n\nconst UTF8 = new TextEncoder();\n\n// One code-point pass implementing profile steps 3 + 4: each maximal\n// White_Space run becomes a single U+0020, and a leading or trailing run is\n// dropped entirely (never emitted), which is exactly collapse-then-trim.\n// `isWhiteSpace16` is the pinned Unicode 16.0 White_Space property —\n// deliberately NOT JavaScript's `\\s`, which also matches U+FEFF, a character\n// the property (and therefore the profile) does not treat as whitespace.\nfunction collapseAndTrimWhiteSpace(input: string): string {\n let out = '';\n let pendingRun = false;\n for (const ch of input) {\n if (isWhiteSpace16(ch.codePointAt(0) as number)) {\n pendingRun = true;\n continue;\n }\n if (pendingRun && out.length > 0) {\n out += ' ';\n }\n pendingRun = false;\n out += ch;\n }\n return out;\n}\n\n// Apply the cardano-poe-pw-norm-v1 profile and return the exact Argon2id\n// password bytes. Throws PASSPHRASE_INPUT_TOO_LONG when the raw input exceeds\n// the pre-normalization bound, ENC_PASSPHRASE_UNNORMALIZABLE when the input\n// cannot normalize stably under Unicode 16.0 (an unpaired surrogate or an\n// unassigned code point), and ENC_PASSPHRASE_EMPTY when the normalized result\n// is the empty string.\nexport function normalizePassphrase(passphrase: string): Uint8Array {\n const rawBytes = UTF8.encode(passphrase);\n if (rawBytes.length > MAX_PASSPHRASE_INPUT_BYTES) {\n throw new EciesSealedPoeError(\n 'PASSPHRASE_INPUT_TOO_LONG',\n `passphrase raw UTF-8 length ${rawBytes.length} exceeds MAX_PASSPHRASE_INPUT_BYTES=${MAX_PASSPHRASE_INPUT_BYTES}`,\n );\n }\n let folded: string;\n try {\n folded = nfkc16(passphrase);\n } catch (error) {\n if (error instanceof Nfkc16Error) {\n throw new EciesSealedPoeError('ENC_PASSPHRASE_UNNORMALIZABLE', error.message, {\n cause: error,\n });\n }\n throw error;\n }\n const normalized = collapseAndTrimWhiteSpace(folded);\n if (normalized.length === 0) {\n throw new EciesSealedPoeError(\n 'ENC_PASSPHRASE_EMPTY',\n 'passphrase normalizes to the empty string',\n );\n }\n return UTF8.encode(normalized);\n}\n","// Raw-seed identity surface. A developer holding a 32-byte seed (e.g. the\n// decoded hex of a key exported from another tool) can derive every keypair,\n// obtain their age recipient strings, get a path-1 Signer, build the\n// RecipientKeyBundle the unwrap dispatch consumes, and decrypt a sealed PoE —\n// all from the public SDK, without a web account envelope.\n//\n// The seed is the only secret this module touches. Callers are responsible for\n// sourcing it securely; the SDK never persists or logs it.\n\nimport {\n deriveEd25519KeypairFromSeed,\n deriveX25519KeypairFromSeed,\n deriveMlKem768X25519KeypairFromSeed,\n type DerivedEd25519KeyPair,\n type DerivedX25519KeyPair,\n type DerivedMlKem768X25519KeyPair,\n} from '@cardanowall/crypto-core/seed-derive';\nimport {\n encodeAgeX25519Recipient,\n encodeAgeXWingRecipient,\n} from '@cardanowall/crypto-core/recipient';\nimport {\n eciesSealedPoeUnwrap,\n type ItemHashes,\n type RecipientKeyBundle,\n type SealedEnvelope,\n type UnwrapResult,\n} from '@cardanowall/crypto-core/sealed-poe';\nimport { signEd25519 } from '@cardanowall/crypto-core/sig';\n\nimport type { Signer } from '../client/types';\n\nexport interface SeedKeys {\n readonly ed25519: DerivedEd25519KeyPair;\n readonly x25519: DerivedX25519KeyPair;\n readonly mlkem768x25519: DerivedMlKem768X25519KeyPair;\n}\n\n// Derive the three identity keypairs from a 32-byte seed: Ed25519 (record\n// signing), X25519 (classical KEM), and ML-KEM-768 + X25519 / X-Wing (hybrid\n// post-quantum KEM). Each keypair is the same byte-for-byte value the account\n// envelope would expose — the seed alone fully determines the identity.\nexport function deriveKeysFromSeed(seed: Uint8Array): SeedKeys {\n return {\n ed25519: deriveEd25519KeypairFromSeed(seed),\n x25519: deriveX25519KeypairFromSeed(seed),\n mlkem768x25519: deriveMlKem768X25519KeypairFromSeed(seed),\n };\n}\n\nexport interface SeedRecipients {\n /** Classical age recipient (\"age1…\") for the X25519 KEM. */\n readonly age: string;\n /** X-Wing hybrid recipient (\"age1pqc…\") for the ML-KEM-768 + X25519 KEM. */\n readonly age1pqc: string;\n}\n\n// The recipient strings other senders use to address this identity. Both\n// always exist for any seed: the X-Wing keypair derives for free, so every\n// identity can receive hybrid sealed records even when it publishes via the\n// classical X25519 path.\nexport function recipientsFromSeed(seed: Uint8Array): SeedRecipients {\n const keys = deriveKeysFromSeed(seed);\n return {\n age: encodeAgeX25519Recipient(keys.x25519.publicKey),\n age1pqc: encodeAgeXWingRecipient(keys.mlkem768x25519.publicKey),\n };\n}\n\n// An in-memory path-1 Signer for the publish helpers / off-host signing\n// surface. The derived Ed25519 secret lives only inside this closure; the\n// SDK's publish path touches just `signerPubkey` (public) and the 64-byte\n// signature (public). The 32-byte HKDF output IS the noble Ed25519 seed, so it\n// feeds `signEd25519` directly.\nexport function signerFromSeed(seed: Uint8Array): Signer {\n const { secretKey, publicKey } = deriveEd25519KeypairFromSeed(seed);\n return {\n signerPubkey: publicKey,\n async sign(sigStructureBytes: Uint8Array): Promise<Uint8Array> {\n return signEd25519({ seed: secretKey, message: sigStructureBytes });\n },\n };\n}\n\n// The unified RecipientKeyBundle for the trial-decrypt / unwrap dispatch. A\n// single active identity contributes a one-element X25519 private-key chain and\n// a one-element X-Wing secret-seed list; the unwrap dispatch selects the right\n// list from `envelope.kem`.\nexport function recipientKeyBundleFromSeed(seed: Uint8Array): RecipientKeyBundle {\n const keys = deriveKeysFromSeed(seed);\n return {\n x25519PrivateKeys: [keys.x25519.secretKey],\n mlkem768x25519SecretSeeds: [keys.mlkem768x25519.secretSeed],\n };\n}\n\nexport interface DecryptSealedFromSeedArgs {\n readonly seed: Uint8Array;\n readonly envelope: SealedEnvelope;\n readonly ciphertext: Uint8Array;\n // The item's plaintext-hash claim, exactly as carried in the record body.\n // Load-bearing for decryption: the hashes map is bound into the slots\n // transcript, so a slot only accepts when the envelope sits under the same\n // hashes claim it was sealed for.\n readonly hashes: ItemHashes;\n}\n\n// Decrypt a sealed PoE envelope + ciphertext from the seed. Builds the bundle\n// and routes through the existing unwrap dispatch, which selects the correct\n// secret list from `envelope.kem` — so the same call decrypts both classical\n// (x25519) and hybrid (mlkem768x25519) records. Returns the discriminated\n// UnwrapResult; it never throws on an authentication failure (wrong key,\n// tampered header, tampered ciphertext) — callers branch on `result.matched`.\nexport function decryptSealedFromSeed(args: DecryptSealedFromSeedArgs): UnwrapResult {\n return eciesSealedPoeUnwrap({\n envelope: args.envelope,\n ciphertext: args.ciphertext,\n hashes: args.hashes,\n recipientKeyBundle: recipientKeyBundleFromSeed(args.seed),\n });\n}\n"]}