@bcts/spqr 1.0.0-alpha.21

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["sha256","shake256","ml_kem768","sha3_512","SCKA_KEY_LABEL","deriveEpochSecret","NoHeaderReceived","HeaderReceived","CHUNK_DATA_SIZE","enc","KeysUnsampled","HeaderSent","EkSentCt1Received","unchunkedSendCt.NoHeaderReceived","unchunkedSendCt.NoHeaderReceived","unchunkedSendEk.KeysUnsampled","sendEk.KeysUnsampled","unchunked.KeysUnsampled","sendEk.KeysUnsampled","send","recv","ucSendEk.KeysUnsampled","sendEk.KeysUnsampled","ucSendEk.HeaderSent","sendEk.KeysSampled","ucSendEk.EkSent","sendEk.HeaderSent","ucSendEk.EkSentCt1Received","sendEk.Ct1Received","sendEk.EkSentCt1Received","ucSendCt.NoHeaderReceived","sendCt.NoHeaderReceived","ucSendCt.HeaderReceived","sendCt.HeaderReceived","ucSendCt.Ct1Sent","sendCt.Ct1Sampled","ucSendCt.Ct1SentEkReceived","sendCt.EkReceivedCt1Sampled","sendCt.Ct1Acknowledged","ucSendCt.Ct2Sent","sendCt.Ct2Sampled","chunkedSend","chunkedRecv"],"sources":["../src/kdf.ts","../src/util.ts","../src/constants.ts","../src/incremental-mlkem768.ts","../src/error.ts","../src/v1/unchunked/send-ct.ts","../src/encoding/gf.ts","../src/encoding/polynomial.ts","../src/authenticator.ts","../src/v1/chunked/send-ek.ts","../src/v1/unchunked/send-ek.ts","../src/v1/chunked/send-ct.ts","../src/v1/chunked/states.ts","../src/v1/chunked/message.ts","../src/v1/chunked/index.ts","../src/v1/chunked/serialize.ts","../src/types.ts","../src/chain.ts","../src/proto/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * KDF wrappers for SPQR (HKDF-SHA256 and HMAC-SHA256).\n */\n\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\n\n/**\n * HKDF-SHA256 key derivation.\n * @param ikm Input key material\n * @param salt Salt (use ZERO_SALT for empty)\n * @param info Context info string or bytes\n * @param length Output length in bytes\n */\nexport function hkdfSha256(\n ikm: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array | string,\n length: number,\n): Uint8Array {\n const infoBytes = typeof info === \"string\" ? new TextEncoder().encode(info) : info;\n return hkdf(sha256, ikm, salt, infoBytes, length);\n}\n\n/**\n * HMAC-SHA256 computation.\n */\nexport function hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array {\n return hmac(sha256, key, data);\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Low-level utility functions for SPQR.\n */\n\n/**\n * Constant-time comparison of two byte arrays.\n * Returns true if they are equal, false otherwise.\n *\n * Uses a XOR accumulator to avoid early-exit timing leaks.\n *\n * Limitation: Unlike Rust (#[inline(never)] + black_box), JavaScript\n * cannot fully prevent JIT optimizations. In Node.js environments,\n * callers requiring stronger guarantees should use\n * crypto.timingSafeEqual directly.\n */\nexport function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) {\n diff |= a[i] ^ b[i];\n }\n return diff === 0;\n}\n\n/** Convert a bigint to 8-byte big-endian Uint8Array */\nexport function bigintToBE8(value: bigint): Uint8Array {\n const buf = new Uint8Array(8);\n const view = new DataView(buf.buffer);\n view.setBigUint64(0, value, false);\n return buf;\n}\n\n/** Convert an 8-byte big-endian Uint8Array to bigint */\nexport function be8ToBigint(buf: Uint8Array): bigint {\n const view = new DataView(buf.buffer, buf.byteOffset, 8);\n return view.getBigUint64(0, false);\n}\n\n/** Convert a number to 4-byte big-endian Uint8Array */\nexport function uint32ToBE4(value: number): Uint8Array {\n const buf = new Uint8Array(4);\n const view = new DataView(buf.buffer);\n view.setUint32(0, value, false);\n return buf;\n}\n\n/** Concatenate multiple Uint8Arrays */\nexport function concat(...arrays: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const a of arrays) total += a.length;\n const result = new Uint8Array(total);\n let offset = 0;\n for (const a of arrays) {\n result.set(a, offset);\n offset += a.length;\n }\n return result;\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Protocol constants for SPQR.\n * Values must match the Rust implementation exactly.\n */\n\n/** Size of each erasure-coded chunk in bytes */\nexport const CHUNK_SIZE = 32;\n\n/** Number of parallel polynomials per chunk (32 bytes / 2 bytes per GF16) */\nexport const NUM_POLYS = 16;\n\n/** GF(2^16) irreducible polynomial */\nexport const GF_POLY = 0x1100b;\n\n/** ML-KEM-768 split public key header size */\nexport const HEADER_SIZE = 64;\n\n/** ML-KEM-768 remaining public key (encapsulation key) */\nexport const ENCAPSULATION_KEY_SIZE = 1152;\n\n/** ML-KEM-768 secret key size */\nexport const DECAPSULATION_KEY_SIZE = 2400;\n\n/** ML-KEM-768 first ciphertext size */\nexport const CIPHERTEXT1_SIZE = 960;\n\n/** ML-KEM-768 second ciphertext size */\nexport const CIPHERTEXT2_SIZE = 128;\n\n/** ML-KEM-768 full public key size */\nexport const PUBLIC_KEY_SIZE = 1184;\n\n/** ML-KEM-768 full ciphertext size */\nexport const FULL_CIPHERTEXT_SIZE = 1088;\n\n/** libcrux incremental encapsulation state size */\nexport const ENCAPSULATION_STATE_SIZE = 2080;\n\n/** KEM shared secret size */\nexport const SHARED_SECRET_SIZE = 32;\n\n/** HMAC-SHA256 MAC size */\nexport const MAC_SIZE = 32;\n\n/** Default max key index jump */\nexport const DEFAULT_MAX_JUMP = 25000;\n\n/** Default max out-of-order keys stored */\nexport const DEFAULT_MAX_OOO_KEYS = 2000;\n\n/** Default chain parameters */\nexport const DEFAULT_CHAIN_PARAMS = {\n maxJump: DEFAULT_MAX_JUMP,\n maxOooKeys: DEFAULT_MAX_OOO_KEYS,\n} as const;\n\n/** Number of epochs to keep prior to the current send epoch */\nexport const EPOCHS_TO_KEEP_PRIOR_TO_SEND_EPOCH = 1;\n\n/** Size of a key entry in KeyHistory: 4 bytes (index BE32) + 32 bytes (key) */\nexport const KEY_ENTRY_SIZE = 36;\n\n// ---- HKDF Labels (must match Rust exactly) ----\n\n/** Chain initialization label (NOTE: two spaces before \"Start\") */\nexport const LABEL_CHAIN_START = \"Signal PQ Ratchet V1 Chain Start\";\n\n/** Chain epoch advancement label */\nexport const LABEL_CHAIN_ADD_EPOCH = \"Signal PQ Ratchet V1 Chain Add Epoch\";\n\n/** Per-message key derivation label */\nexport const LABEL_CHAIN_NEXT = \"Signal PQ Ratchet V1 Chain Next\";\n\n/** Authenticator key ratchet label */\nexport const LABEL_AUTH_UPDATE = \"Signal_PQCKA_V1_MLKEM768:Authenticator Update\";\n\n/** Ciphertext MAC label */\nexport const LABEL_CT_MAC = \"Signal_PQCKA_V1_MLKEM768:ciphertext\";\n\n/** Header MAC label */\nexport const LABEL_HDR_MAC = \"Signal_PQCKA_V1_MLKEM768:ekheader\";\n\n/** Epoch secret derivation label */\nexport const LABEL_SCKA_KEY = \"Signal_PQCKA_V1_MLKEM768:SCKA Key\";\n\n/** 32-byte zero salt used in HKDF */\nexport const ZERO_SALT = new Uint8Array(32);\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * True incremental ML-KEM-768 implementation.\n *\n * Implements the libcrux-compatible incremental encapsulation split:\n *\n * - generate(): Splits the ML-KEM-768 public key into:\n * hdr (pk1, 64 bytes) = rho(32) + H(ek)(32) -- where H = SHA3-256\n * ek (pk2, 1152 bytes) = ByteEncode12(tHat) -- the NTT vector\n *\n * - encaps1(hdr, rng): Uses only rho and H(ek) from the header to produce\n * a REAL ct1 (960 bytes), shared secret (32 bytes), and\n * encapsulation state (2080 bytes) for encaps2.\n *\n * - encaps2(ek, es): Completes the encapsulation using the tHat from pk2\n * and the stored NTT randomness. Returns ct2 (128 bytes).\n *\n * - decaps(dk, ct1, ct2): Standard ML-KEM-768 decapsulation.\n *\n * Wire-compatible with Signal's Rust libcrux incremental implementation.\n */\n\nimport { sha3_256, sha3_512, shake256 } from \"@noble/hashes/sha3.js\";\nimport { u32 } from \"@noble/hashes/utils.js\";\nimport { genCrystals, XOF128 } from \"@noble/post-quantum/_crystals.js\";\nimport { ml_kem768 } from \"@noble/post-quantum/ml-kem.js\";\nimport type { RandomBytes } from \"./types.js\";\n\n// ---- ML-KEM-768 constants ----\n\nconst N = 256;\nconst Q = 3329;\nconst F = 3303;\nconst ROOT_OF_UNITY = 17;\nconst K = 3;\nconst ETA1 = 2;\nconst ETA2 = 2;\nconst DU = 10;\nconst DV = 4;\n\n// ---- Size constants ----\n\n/** Size of the public key header: rho(32) + H(ek)(32) */\nexport const HEADER_SIZE = 64;\n\n/** Size of the encapsulation key: ByteEncode12(tHat) = 3 * 384 = 1152 bytes */\nexport const EK_SIZE = 1152;\n\n/** Size of the decapsulation (secret) key */\nexport const DK_SIZE = 2400;\n\n/** Size of the first ciphertext fragment (ct[0..960]) */\nexport const CT1_SIZE = 960;\n\n/** Size of the second ciphertext fragment (ct[960..1088]) */\nexport const CT2_SIZE = 128;\n\n/** Size of the KEM shared secret */\nexport const SS_SIZE = 32;\n\n/** Standard ML-KEM-768 full public key size */\nexport const FULL_PK_SIZE = 1184;\n\n/** Standard ML-KEM-768 full ciphertext size */\nexport const FULL_CT_SIZE = 1088;\n\n/** Size of the keygen seed */\nexport const KEYGEN_SEED_SIZE = 64;\n\n/** Size of the encapsulation randomness (message m) */\nexport const ENCAPS_SEED_SIZE = 32;\n\n/**\n * Size of the encapsulation state:\n * r_as_ntt: K(3) * N(256) * 2 = 1536 bytes\n * error2: N(256) * 2 = 512 bytes\n * randomness: 32 bytes\n * Total: 2080 bytes\n */\nexport const ES_SIZE = 2080;\n\n// ---- Initialize crystals NTT machinery ----\n\nconst { mod, nttZetas, NTT, bitsCoder } = genCrystals({\n N,\n Q,\n F,\n ROOT_OF_UNITY,\n newPoly: (n: number): Uint16Array => new Uint16Array(n),\n brvBits: 7,\n isKyber: true,\n});\n\n// ---- Polynomial operations (copied from noble ml-kem.ts, closure-scoped) ----\n\ntype Poly = Uint16Array;\n\nfunction polyAdd(a: Poly, b: Poly): void {\n for (let i = 0; i < N; i++) a[i] = mod(a[i] + b[i]);\n}\n\nfunction BaseCaseMultiply(\n a0: number,\n a1: number,\n b0: number,\n b1: number,\n zeta: number,\n): { c0: number; c1: number } {\n const c0 = mod(a1 * b1 * zeta + a0 * b0);\n const c1 = mod(a0 * b1 + a1 * b0);\n return { c0, c1 };\n}\n\nfunction MultiplyNTTs(f: Poly, g: Poly): Poly {\n for (let i = 0; i < N / 2; i++) {\n let z = nttZetas[64 + (i >> 1)];\n if ((i & 1) !== 0) 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;\n}\n\ntype XofGet = ReturnType<ReturnType<typeof XOF128>[\"get\"]>;\n\nfunction SampleNTT(xof: XofGet): Poly {\n const r: Poly = new Uint16Array(N);\n for (let j = 0; j < N; ) {\n const b = xof();\n if (b.length % 3 !== 0) 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;\n}\n\nfunction sampleCBD(seed: Uint8Array, nonce: number, eta: number): Poly {\n const len = (eta * N) / 4;\n const buf = shake256\n .create({ dkLen: len })\n .update(seed)\n .update(new Uint8Array([nonce]))\n .digest();\n const r: Poly = new Uint16Array(N);\n const b32 = u32(buf);\n let bitLen = 0;\n let p = 0;\n let bb = 0;\n let t0 = 0;\n for (let b of b32) {\n for (let j = 0; j < 32; j++) {\n bb += b & 1;\n b >>= 1;\n bitLen += 1;\n if (bitLen === eta) {\n t0 = bb;\n bb = 0;\n } else if (bitLen === 2 * eta) {\n r[p++] = mod(t0 - bb);\n bb = 0;\n bitLen = 0;\n }\n }\n }\n if (bitLen !== 0) throw new Error(`sampleCBD: leftover bits: ${bitLen}`);\n return r;\n}\n\n// ---- Compress/decompress coders ----\n\nconst compress = (d: number): { encode: (i: number) => number; decode: (i: number) => number } => {\n if (d >= 12) return { encode: (i: number) => i, decode: (i: number) => i };\n const a = 2 ** (d - 1);\n return {\n encode: (i: number) => ((i << d) + Q / 2) / Q,\n decode: (i: number) => (i * Q + a) >>> d,\n };\n};\n\nconst polyCoder = (d: number): ReturnType<typeof bitsCoder> => bitsCoder(d, compress(d));\n\n// Coders for encoding/decoding polynomials\nconst poly12 = polyCoder(12); // for tHat encoding (ByteEncode12)\nconst polyDU = polyCoder(DU); // for u compression (du=10)\nconst polyDV = polyCoder(DV); // for v compression (dv=4)\nconst poly1 = polyCoder(1); // for message encoding (1-bit)\n\n// ---- Key material ----\n\n/** Generated ML-KEM-768 key material, split for incremental protocol */\nexport interface Keys {\n /** Public key header: rho(32) + SHA3-256(full_pk)(32) */\n hdr: Uint8Array;\n /** Encapsulation key: ByteEncode12(tHat) = 1152 bytes */\n ek: Uint8Array;\n /** Decapsulation (secret) key: full 2400-byte ML-KEM-768 secret key */\n dk: Uint8Array;\n}\n\n/** Result of encaps1: REAL ct1, shared secret, and encapsulation state */\nexport interface Encaps1Result {\n /** REAL ct1 (960 bytes) */\n ct1: Uint8Array;\n /** Encapsulation state (2080 bytes): r_as_ntt(1536) + error2(512) + m(32) */\n es: Uint8Array;\n /** REAL shared secret (32 bytes) */\n sharedSecret: Uint8Array;\n}\n\n// ---- Encapsulation state encoding ----\n\n/**\n * Encode the encapsulation state as 2080 bytes:\n * r_as_ntt: K polys, each 256 coefficients as uint16 LE = 1536 bytes\n * error2: 1 poly, 256 coefficients as uint16 LE = 512 bytes\n * randomness: 32 bytes (the message m)\n */\nfunction encodeState(rHat: Poly[], e2: Poly, m: Uint8Array): Uint8Array {\n const state = new Uint8Array(ES_SIZE);\n let offset = 0;\n\n // r_as_ntt: K polynomials\n for (let k = 0; k < K; k++) {\n const poly = rHat[k];\n for (let i = 0; i < N; i++) {\n const val = poly[i];\n state[offset++] = val & 0xff;\n state[offset++] = (val >> 8) & 0xff;\n }\n }\n\n // error2: 1 polynomial\n for (let i = 0; i < N; i++) {\n const val = e2[i];\n state[offset++] = val & 0xff;\n state[offset++] = (val >> 8) & 0xff;\n }\n\n // randomness (message m)\n state.set(m, offset);\n\n return state;\n}\n\n/**\n * Decode the encapsulation state from 2080 bytes.\n * Includes the Issue 1275 endianness workaround.\n */\nfunction decodeState(state: Uint8Array): {\n rHat: Poly[];\n e2: Poly;\n m: Uint8Array;\n} {\n // Apply Issue 1275 workaround\n const fixedState = fixIssue1275(state);\n const st = fixedState ?? state;\n\n let offset = 0;\n\n // r_as_ntt: K polynomials\n const rHat: Poly[] = [];\n for (let k = 0; k < K; k++) {\n const poly = new Uint16Array(N);\n for (let i = 0; i < N; i++) {\n poly[i] = st[offset] | (st[offset + 1] << 8);\n offset += 2;\n }\n rHat.push(poly);\n }\n\n // error2: 1 polynomial\n const e2 = new Uint16Array(N);\n for (let i = 0; i < N; i++) {\n e2[i] = st[offset] | (st[offset + 1] << 8);\n offset += 2;\n }\n\n // randomness (message m)\n const m = st.slice(offset, offset + 32);\n\n return { rHat, e2, m };\n}\n\n// ---- Issue 1275 Endianness Workaround ----\n\n/**\n * Port of Rust's potentially_fix_state_incorrectly_encoded_by_libcrux_issue_1275.\n *\n * Due to https://github.com/cryspen/libcrux/issues/1275, the encapsulation\n * state may contain error2 coefficients with wrong endianness.\n *\n * Error2 values should be in [-2, 2] (ETA2=2 for ML-KEM-768).\n * As uint16 LE, valid values are: 0x0000, 0x0001, 0x0002, 0xFFFF (-1), 0xFFFE (-2).\n * Bad-endian equivalents: 0x0100, 0x0200, 0xFEFF.\n *\n * Returns a fixed copy if endianness is wrong, or null if state is OK.\n */\nfunction fixIssue1275(es: Uint8Array): Uint8Array | null {\n // error2 is at bytes [1536..2048] (after r_as_ntt, before randomness)\n const E2_START = K * N * 2; // 1536\n const E2_END = E2_START + N * 2; // 2048\n\n for (let i = E2_START; i < E2_END; i += 2) {\n const lo = es[i];\n const hi = es[i + 1];\n const val = lo | (hi << 8); // interpret as i16 LE\n\n // 0x0000 and 0xFFFF have same representation in both endiannesses\n if (val === 0x0000 || val === 0xffff) continue;\n\n // Good LE values: 0x0001, 0x0002, 0xFFFE\n if (val === 0x0001 || val === 0x0002 || val === 0xfffe) {\n return null; // Already correct\n }\n\n // Bad (big-endian) values: 0x0100, 0x0200, 0xFEFF\n if (val === 0x0100 || val === 0x0200 || val === 0xfeff) {\n return flipEndianness(es);\n }\n\n // Unknown value -- return null (use as-is)\n return null;\n }\n\n return null;\n}\n\n/**\n * Flip the endianness of all i16 values in the encapsulation state.\n * The last 32 bytes (randomness) are NOT flipped.\n */\nfunction flipEndianness(es: Uint8Array): Uint8Array {\n const fixed = new Uint8Array(es);\n const coeffEnd = es.length - 32; // don't flip the last 32 bytes (randomness)\n for (let i = 0; i < coeffEnd; i += 2) {\n const tmp = fixed[i];\n fixed[i] = fixed[i + 1];\n fixed[i + 1] = tmp;\n }\n return fixed;\n}\n\n// ---- Key generation ----\n\n/**\n * Generate an ML-KEM-768 keypair and split the public key.\n *\n * The ML-KEM-768 public key (1184 bytes) is:\n * tHat = pk[0..1152] (ByteEncode12 of NTT vector)\n * rho = pk[1152..1184] (32-byte seed)\n *\n * The incremental split produces:\n * hdr (pk1) = rho(32) + SHA3-256(pk)(32) = 64 bytes\n * ek (pk2) = tHat(1152) = ByteEncode12(tHat) = 1152 bytes\n *\n * @param rng - Random byte generator; must provide at least 64 bytes\n * @returns Split key material\n */\nexport function generate(rng: RandomBytes): Keys {\n const seed = rng(KEYGEN_SEED_SIZE);\n const { publicKey, secretKey } = ml_kem768.keygen(seed);\n\n // Standard pk layout: tHat(1152) || rho(32)\n const tHat = publicKey.slice(0, EK_SIZE); // 1152 bytes\n const rho = publicKey.slice(EK_SIZE); // 32 bytes\n const hEk = sha3_256(publicKey); // H(ek) = SHA3-256(full pk)\n\n // pk1 (header) = rho(32) || H(ek)(32)\n const hdr = new Uint8Array(HEADER_SIZE);\n hdr.set(rho, 0);\n hdr.set(hEk, 32);\n\n return {\n hdr,\n ek: tHat,\n dk: secretKey,\n };\n}\n\n// ---- Encapsulation Phase 1 ----\n\n/**\n * Phase 1 of true incremental encapsulation.\n *\n * Uses only rho and H(ek) from the 64-byte header to produce:\n * - REAL ct1 (960 bytes): compress_du(u) where u = NTT^-1(A^T * rHat) + e1\n * - REAL shared secret: K-hat from SHA3-512(m || H(ek))\n * - Encapsulation state (2080 bytes): r_as_ntt + error2 + m\n *\n * @param hdr - The 64-byte header: rho(32) + H(ek)(32)\n * @param rng - Random byte generator\n * @returns Real ct1, encapsulation state, and real shared secret\n */\nexport function encaps1(hdr: Uint8Array, rng: RandomBytes): Encaps1Result {\n const rho = hdr.slice(0, 32);\n const hEk = hdr.slice(32, 64);\n\n // Step 1: m = random 32 bytes\n const m = rng(ENCAPS_SEED_SIZE);\n\n // Step 2: kr = SHA3-512(m || H(ek)) -> K-hat(32) || r(32)\n const kr = sha3_512.create().update(m).update(hEk).digest();\n const kHat = kr.slice(0, 32);\n const r = kr.slice(32, 64);\n\n // Step 3: Sample rHat[i] = NTT(CBD(r, i, ETA1))\n const rHat: Poly[] = [];\n for (let i = 0; i < K; i++) {\n rHat.push(NTT.encode(sampleCBD(r, i, ETA1)));\n }\n\n // Step 4: Generate A from rho via XOF128, compute u\n const x = XOF128(rho);\n const u: Poly[] = [];\n for (let i = 0; i < K; i++) {\n const e1 = sampleCBD(r, 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));\n polyAdd(tmp, MultiplyNTTs(aij, rHat[j].slice() as Poly));\n }\n polyAdd(e1, NTT.decode(tmp));\n u.push(e1);\n }\n x.clean();\n\n // Step 5: ct1 = compress_du(u) = encode each u[i] with du=10\n const ct1 = new Uint8Array(CT1_SIZE);\n for (let i = 0; i < K; i++) {\n const encoded = polyDU.encode(u[i]);\n ct1.set(encoded, i * polyDU.bytesLen);\n }\n\n // Step 6: e2 = CBD(r, 2*K, ETA2)\n const e2 = sampleCBD(r, 2 * K, ETA2);\n\n // Step 7: Encode state\n const es = encodeState(rHat, e2, m);\n\n return {\n ct1,\n es,\n sharedSecret: kHat,\n };\n}\n\n// ---- Encapsulation Phase 2 ----\n\n/**\n * Phase 2 of true incremental encapsulation.\n *\n * Uses the tHat from pk2 (ek) and the stored NTT randomness to compute ct2.\n *\n * @param ek - The 1152-byte encapsulation key (ByteEncode12(tHat))\n * @param es - The 2080-byte encapsulation state from encaps1\n * @returns ct2 (128 bytes) ONLY\n */\nexport function encaps2(ek: Uint8Array, es: Uint8Array): Uint8Array {\n const { rHat, e2, m } = decodeState(es);\n\n // Decode tHat from ek (ByteDecode12)\n const tHat: Poly[] = [];\n for (let i = 0; i < K; i++) {\n const slice = ek.subarray(i * poly12.bytesLen, (i + 1) * poly12.bytesLen);\n tHat.push(poly12.decode(slice));\n }\n\n // Compute v = NTT^-1(sum(tHat[i] * rHat[i])) + e2 + Decompress1(m)\n const tmp = new Uint16Array(N);\n for (let i = 0; i < K; i++) {\n polyAdd(tmp, MultiplyNTTs(tHat[i].slice() as Poly, rHat[i].slice() as Poly));\n }\n const v = NTT.decode(tmp);\n polyAdd(v, e2);\n\n // Decompress1(m) = decode m as 1-bit polynomial\n const mPoly = poly1.decode(m);\n polyAdd(v, mPoly);\n\n // ct2 = compress_dv(v)\n return polyDV.encode(v);\n}\n\n// ---- Decapsulation ----\n\n/**\n * Decapsulate a split ciphertext using the decapsulation key.\n *\n * Concatenates ct1 (960 bytes) and ct2 (128 bytes) into a standard\n * 1088-byte ML-KEM-768 ciphertext, then performs standard decapsulation.\n *\n * @param dk - The 2400-byte decapsulation (secret) key\n * @param ct1 - First ciphertext fragment (960 bytes)\n * @param ct2 - Second ciphertext fragment (128 bytes)\n * @returns The 32-byte shared secret\n */\nexport function decaps(dk: Uint8Array, ct1: Uint8Array, ct2: Uint8Array): Uint8Array {\n const ct = new Uint8Array(FULL_CT_SIZE);\n ct.set(ct1.subarray(0, CT1_SIZE), 0);\n ct.set(ct2.subarray(0, CT2_SIZE), CT1_SIZE);\n return ml_kem768.decapsulate(ct, dk);\n}\n\n// ---- Validation ----\n\n/**\n * Check whether an encapsulation key is consistent with a header.\n *\n * Reconstructs the full public key from pk2 (tHat) and pk1[0..32] (rho),\n * computes SHA3-256 of the full pk, and compares with H(ek) in the header.\n *\n * @param ek - Encapsulation key (1152 bytes = ByteEncode12(tHat))\n * @param hdr - Header (64 bytes = rho(32) + H(ek)(32))\n * @returns true if ek is consistent with the header\n */\nexport function ekMatchesHeader(ek: Uint8Array, hdr: Uint8Array): boolean {\n if (hdr.length < HEADER_SIZE || ek.length < EK_SIZE) {\n return false;\n }\n\n const rho = hdr.slice(0, 32);\n const expectedHash = hdr.slice(32, 64);\n\n // Reconstruct full pk: tHat(1152) || rho(32)\n const pk = new Uint8Array(FULL_PK_SIZE);\n pk.set(ek.subarray(0, EK_SIZE), 0);\n pk.set(rho, EK_SIZE);\n\n // Compute H(pk) and compare\n const actualHash = sha3_256(pk);\n\n // Constant-time comparison\n if (actualHash.length !== expectedHash.length) return false;\n let diff = 0;\n for (let i = 0; i < actualHash.length; i++) {\n diff |= actualHash[i] ^ expectedHash[i];\n }\n return diff === 0;\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Error types for the SPQR protocol.\n */\n\nexport class SpqrError extends Error {\n constructor(\n message: string,\n public readonly code: SpqrErrorCode,\n public readonly detail?: unknown,\n ) {\n super(message);\n this.name = \"SpqrError\";\n }\n}\n\nexport enum SpqrErrorCode {\n StateDecode = \"STATE_DECODE\",\n NotImplemented = \"NOT_IMPLEMENTED\",\n MsgDecode = \"MSG_DECODE\",\n MacVerifyFailed = \"MAC_VERIFY_FAILED\",\n EpochOutOfRange = \"EPOCH_OUT_OF_RANGE\",\n EncodingDecoding = \"ENCODING_DECODING\",\n Serialization = \"SERIALIZATION\",\n VersionMismatch = \"VERSION_MISMATCH\",\n MinimumVersion = \"MINIMUM_VERSION\",\n KeyJump = \"KEY_JUMP\",\n KeyTrimmed = \"KEY_TRIMMED\",\n KeyAlreadyRequested = \"KEY_ALREADY_REQUESTED\",\n ErroneousDataReceived = \"ERRONEOUS_DATA_RECEIVED\",\n SendKeyEpochDecreased = \"SEND_KEY_EPOCH_DECREASED\",\n InvalidParams = \"INVALID_PARAMS\",\n ChainNotAvailable = \"CHAIN_NOT_AVAILABLE\",\n}\n\nexport class EncodingError extends Error {\n constructor(\n message: string,\n public readonly inner?: PolynomialError,\n ) {\n super(message);\n this.name = \"EncodingError\";\n }\n}\n\nexport class PolynomialError extends Error {\n constructor(\n message: string,\n public readonly code:\n | \"MESSAGE_LENGTH_EVEN\"\n | \"MESSAGE_LENGTH_TOO_LONG\"\n | \"SERIALIZATION_INVALID\",\n ) {\n super(message);\n this.name = \"PolynomialError\";\n }\n}\n\nexport class AuthenticatorError extends Error {\n constructor(\n message: string,\n public readonly code:\n | \"INVALID_CT_MAC\"\n | \"INVALID_HDR_MAC\"\n | \"ROOT_KEY_PRESENT\"\n | \"ROOT_KEY_MISSING\"\n | \"MAC_KEY_PRESENT\"\n | \"MAC_KEY_MISSING\",\n ) {\n super(message);\n this.name = \"AuthenticatorError\";\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Unchunked send_ct state machine for SPQR V1.\n *\n * Ported from Signal's spqr crate: v1/unchunked/send_ct.rs\n *\n * True incremental ML-KEM-768 implementation (Phase 9):\n *\n * - sendCt1(rng) performs encaps1 using only the header, producing\n * a REAL ct1 and shared secret. The epoch secret is derived here.\n *\n * - recvEk(ek) validates the encapsulation key against the header\n * and stores it for encaps2.\n *\n * - sendCt2() calls encaps2(ek, es) to produce ct2, then MACs ct1||ct2.\n *\n * State transitions:\n * NoHeaderReceived --recvHeader(epoch, hdr, mac)--> HeaderReceived\n * HeaderReceived --sendCt1(rng)----------------> Ct1Sent + REAL ct1 + EpochSecret\n * Ct1Sent --recvEk(ek)------------------> Ct1SentEkReceived\n * Ct1SentEkReceived --sendCt2()-------------------> Ct2Sent + (ct2, mac)\n * Ct2Sent (terminal -- caller creates next KeysUnsampled)\n */\n\nimport { type Authenticator } from \"../../authenticator.js\";\nimport { hkdfSha256 } from \"../../kdf.js\";\nimport { concat, bigintToBE8 } from \"../../util.js\";\nimport { ZERO_SALT, LABEL_SCKA_KEY } from \"../../constants.js\";\nimport { encaps1, encaps2, ekMatchesHeader } from \"../../incremental-mlkem768.js\";\nimport { SpqrError, SpqrErrorCode } from \"../../error.js\";\nimport type { Epoch, EpochSecret, RandomBytes } from \"../../types.js\";\n\n// Pre-encode the SCKA label\nconst SCKA_KEY_LABEL = new TextEncoder().encode(LABEL_SCKA_KEY);\n\n/**\n * Derive the epoch secret from the KEM shared secret.\n *\n * HKDF-SHA256(ikm=sharedSecret, salt=ZERO_SALT,\n * info=LABEL_SCKA_KEY || epoch_be8, length=32)\n *\n * Matches Rust: info = [b\"Signal_PQCKA_V1_MLKEM768:SCKA Key\", epoch.to_be_bytes()].concat()\n */\nfunction deriveEpochSecret(epoch: Epoch, sharedSecret: Uint8Array): EpochSecret {\n const info = concat(SCKA_KEY_LABEL, bigintToBE8(epoch));\n const secret = hkdfSha256(sharedSecret, ZERO_SALT, info, 32);\n return { epoch, secret };\n}\n\n/** Result of Ct1SentEkReceived.sendCt2 */\nexport interface SendCt2Result {\n /** Next state (terminal for this epoch's send_ct) */\n state: Ct2Sent;\n /** The 128-byte second ciphertext fragment */\n ct2: Uint8Array;\n /** The HMAC-SHA256 MAC over the full ciphertext (ct1 || ct2) */\n mac: Uint8Array;\n}\n\n// ---- State: NoHeaderReceived ----\n\n/**\n * Waiting to receive the header from the send_ek peer.\n */\nexport class NoHeaderReceived {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n ) {}\n\n /**\n * Receive the header and verify its MAC.\n *\n * @param epoch - The epoch for this exchange (must match current epoch)\n * @param hdr - The 64-byte public key header\n * @param mac - The 32-byte HMAC-SHA256 MAC over the header\n * @returns Next state\n * @throws {AuthenticatorError} If the header MAC is invalid\n */\n recvHeader(epoch: Epoch, hdr: Uint8Array, mac: Uint8Array): HeaderReceived {\n // Verify header MAC\n this.auth.verifyHdr(epoch, hdr, mac);\n\n return new HeaderReceived(this.epoch, this.auth, hdr);\n }\n}\n\n// ---- State: HeaderReceived ----\n\n/**\n * The header has been received and verified. Ready to produce ct1.\n *\n * In the true incremental ML-KEM approach, sendCt1 performs encaps1\n * using only the header (rho + H(ek)), producing REAL ct1 and shared\n * secret. The epoch secret is derived here.\n */\nexport class HeaderReceived {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly hdr: Uint8Array,\n ) {}\n\n /**\n * Generate encapsulation randomness and produce REAL ct1.\n *\n * Performs encaps1 using the header to produce:\n * - Real ct1 (960 bytes)\n * - Real shared secret -> epoch secret\n * - Encapsulation state for later encaps2\n *\n * The authenticator is updated with the derived epoch secret.\n *\n * @param rng - Random byte generator\n * @returns [nextState, real_ct1, epochSecret]\n */\n sendCt1(rng: RandomBytes): [Ct1Sent, Uint8Array, EpochSecret] {\n const { ct1, es, sharedSecret } = encaps1(this.hdr, rng);\n\n // Derive epoch secret (with epoch in HKDF info, matching Rust)\n const epochSecret = deriveEpochSecret(this.epoch, sharedSecret);\n\n // Update authenticator with the HKDF-derived secret at current epoch\n const auth = this.auth.clone();\n auth.update(this.epoch, epochSecret.secret);\n\n const nextState = new Ct1Sent(this.epoch, auth, this.hdr, es, ct1);\n\n return [nextState, ct1, epochSecret];\n }\n}\n\n// ---- State: Ct1Sent ----\n\n/**\n * Real ct1 has been produced. Waiting for the encapsulation key.\n *\n * Stores hdr, es(2080), and ct1(960) for the encaps2 phase.\n */\nexport class Ct1Sent {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly hdr: Uint8Array,\n public readonly es: Uint8Array,\n public readonly ct1: Uint8Array,\n ) {}\n\n /**\n * Receive the encapsulation key and validate it against the header.\n *\n * In the true incremental approach, this simply validates and stores\n * the ek for later use in sendCt2. No encapsulation happens here.\n *\n * @param ek - The 1152-byte encapsulation key from the send_ek peer\n * @returns Next state\n * @throws {SpqrError} If the ek does not match the header\n */\n recvEk(ek: Uint8Array): Ct1SentEkReceived {\n if (!ekMatchesHeader(ek, this.hdr)) {\n throw new SpqrError(\n \"Encapsulation key does not match header\",\n SpqrErrorCode.ErroneousDataReceived,\n );\n }\n\n return new Ct1SentEkReceived(this.epoch, this.auth, this.es, ek, this.ct1);\n }\n}\n\n// ---- State: Ct1SentEkReceived ----\n\n/**\n * The encapsulation key has been received and validated.\n * Ready to send ct2.\n *\n * Stores es(2080), ek(1152), and ct1(960) for encaps2 + MAC.\n */\nexport class Ct1SentEkReceived {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly es: Uint8Array,\n public readonly ek: Uint8Array,\n public readonly ct1: Uint8Array,\n ) {}\n\n /**\n * Produce ct2 by calling encaps2, then MAC over ct1 || ct2.\n *\n * @returns Result with next state, ct2, and MAC\n */\n sendCt2(): SendCt2Result {\n // encaps2 produces ct2 only\n const ct2 = encaps2(this.ek, this.es);\n\n // MAC over the full ciphertext: ct1 || ct2\n const fullCt = concat(this.ct1, ct2);\n const mac = this.auth.macCt(this.epoch, fullCt);\n\n const state = new Ct2Sent(this.epoch, this.auth);\n\n return {\n state,\n ct2,\n mac,\n };\n }\n}\n\n// ---- State: Ct2Sent ----\n\n/**\n * Terminal state for this epoch's send_ct exchange.\n *\n * The caller is responsible for creating the next epoch's\n * send_ek::KeysUnsampled state from the epoch and auth.\n */\nexport class Ct2Sent {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n ) {}\n\n /** The next epoch for the send_ek side */\n get nextEpoch(): Epoch {\n return this.epoch + 1n;\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * GF(2^16) Galois field arithmetic.\n * Ported from the Rust SPQR implementation.\n *\n * Primitive polynomial: x^16 + x^12 + x^3 + x + 1 (0x1100b)\n */\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Primitive polynomial for GF(2^16): x^16 + x^12 + x^3 + x + 1 */\nexport const POLY = 0x1_100b;\n\n// ---------------------------------------------------------------------------\n// Precomputed reduction table (256 entries)\n// ---------------------------------------------------------------------------\n\n/**\n * Build one entry of the reduction table.\n *\n * Given a single byte `a` that appears in positions [16..23] or [24..31] of\n * a 32-bit product, compute the 16-bit XOR mask needed to reduce those bits\n * modulo POLY.\n */\nfunction reduceFromByte(a: number): number {\n let byte = a;\n let out = 0;\n for (let i = 7; i >= 0; i--) {\n if (((1 << i) & byte) !== 0) {\n out ^= POLY << i;\n byte ^= ((POLY << i) >>> 16) & 0xff;\n }\n }\n return out & 0xffff;\n}\n\n/** Precomputed 256-entry lookup table for polynomial reduction. */\nconst REDUCE_BYTES: Uint16Array = /* @__PURE__ */ (() => {\n const table = new Uint16Array(256);\n for (let i = 0; i < 256; i++) {\n table[i] = reduceFromByte(i);\n }\n return table;\n})();\n\n// ---------------------------------------------------------------------------\n// Low-level polynomial arithmetic (operates on raw u16/u32 numbers)\n// ---------------------------------------------------------------------------\n\n/**\n * Polynomial multiplication in GF(2)[x] (no reduction).\n *\n * Both `a` and `b` must be in the range [0, 0xffff].\n * The result may be up to 31 bits wide.\n */\nfunction polyMul(a: number, b: number): number {\n let acc = 0;\n for (let shift = 0; shift < 16; shift++) {\n if ((b & (1 << shift)) !== 0) {\n acc ^= a << shift;\n }\n }\n // Keep as unsigned 32-bit\n return acc >>> 0;\n}\n\n/**\n * Reduce a 32-bit polynomial product modulo POLY, yielding a 16-bit result.\n *\n * Uses the precomputed REDUCE_BYTES table to process the top two bytes.\n */\nexport function polyReduce(v: number): number {\n let r = v >>> 0;\n // Reduce byte at positions [24..31]\n r ^= REDUCE_BYTES[(r >>> 24) & 0xff] << 8;\n // Reduce byte at positions [16..23]\n r ^= REDUCE_BYTES[(r >>> 16) & 0xff];\n return r & 0xffff;\n}\n\n/**\n * Full GF(2^16) multiplication of two raw u16 values.\n * Returns a u16 result.\n */\nfunction mulRaw(a: number, b: number): number {\n return polyReduce(polyMul(a, b));\n}\n\n// ---------------------------------------------------------------------------\n// GF16 class\n// ---------------------------------------------------------------------------\n\n/**\n * An element of GF(2^16).\n *\n * The `value` field holds a 16-bit unsigned integer in [0, 65535].\n */\nexport class GF16 {\n readonly value: number;\n\n constructor(value: number) {\n this.value = value & 0xffff;\n }\n\n // -- Static constants -----------------------------------------------------\n\n static readonly ZERO = new GF16(0);\n static readonly ONE = new GF16(1);\n\n // -- Arithmetic -----------------------------------------------------------\n\n /** Addition in GF(2^n) is XOR. */\n add(other: GF16): GF16 {\n return new GF16(this.value ^ other.value);\n }\n\n /** Subtraction in GF(2^n) is the same as addition (XOR). */\n sub(other: GF16): GF16 {\n return this.add(other);\n }\n\n /** Multiplication in GF(2^16) using polynomial long-multiplication + reduction. */\n mul(other: GF16): GF16 {\n return new GF16(mulRaw(this.value, other.value));\n }\n\n /**\n * Division in GF(2^16).\n *\n * Computes `this / other` via Fermat's little theorem:\n * other^(-1) = other^(2^16 - 2)\n *\n * The loop accumulates the inverse through repeated squaring:\n * After 15 iterations (i = 1..15):\n * out = this * other^(2^16 - 2) = this * other^(-1)\n *\n * Throws if `other` is zero.\n */\n div(other: GF16): GF16 {\n if (other.value === 0) {\n throw new Error(\"GF16: division by zero\");\n }\n\n let sqVal = mulRaw(other.value, other.value); // other^2\n let outVal = this.value;\n\n for (let i = 1; i < 16; i++) {\n // Compute both products using the OLD square value\n const newSqVal = mulRaw(sqVal, sqVal);\n const newOutVal = mulRaw(sqVal, outVal);\n sqVal = newSqVal;\n outVal = newOutVal;\n }\n\n return new GF16(outVal);\n }\n\n // -- Comparison -----------------------------------------------------------\n\n equals(other: GF16): boolean {\n return this.value === other.value;\n }\n\n // -- Display --------------------------------------------------------------\n\n toString(): string {\n return `GF16(0x${this.value.toString(16).padStart(4, \"0\")})`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Parallel multiplication\n// ---------------------------------------------------------------------------\n\n/**\n * Multiply every element of `into` by `a` in-place.\n *\n * This is the TypeScript equivalent of Rust's `parallel_mult` which benefits\n * from SIMD on native platforms. Here we just iterate.\n */\nexport function parallelMult(a: GF16, into: GF16[]): void {\n const av = a.value;\n for (let i = 0; i < into.length; i++) {\n into[i] = new GF16(mulRaw(av, into[i].value));\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Polynomial erasure coding over GF(2^16).\n * Ported from the Rust SPQR implementation.\n *\n * The encoder splits a message into 16 parallel polynomials and can produce\n * an unlimited number of coded chunks. Any sufficient subset of chunks\n * allows the decoder to reconstruct the original message via Lagrange\n * interpolation.\n */\n\nimport { GF16, parallelMult } from \"./gf.js\";\n\n// ---------------------------------------------------------------------------\n// Error type\n// ---------------------------------------------------------------------------\n\nexport class PolynomialError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PolynomialError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A point on a polynomial in GF(2^16). */\nexport interface Pt {\n x: GF16;\n y: GF16;\n}\n\n/** A coded chunk: an index plus exactly 32 bytes of data. */\nexport interface Chunk {\n index: number; // u16\n data: Uint8Array; // exactly 32 bytes\n}\n\n/** Encoder interface. */\nexport interface Encoder {\n nextChunk(): Chunk;\n}\n\n/** Decoder interface. */\nexport interface Decoder {\n addChunk(chunk: Chunk): void;\n decodedMessage(): Uint8Array | null;\n}\n\n// ---------------------------------------------------------------------------\n// Number of polynomials used for interleaving\n// ---------------------------------------------------------------------------\n\nconst NUM_POLYS = 16;\nconst CHUNK_DATA_SIZE = 32; // 16 GF16 values * 2 bytes each\nconst MAX_MESSAGE_LENGTH = (1 << 16) * NUM_POLYS; // 1,048,576 bytes (matches Rust)\n\n// ---------------------------------------------------------------------------\n// Poly class\n// ---------------------------------------------------------------------------\n\n/**\n * A polynomial over GF(2^16) in coefficient form.\n *\n * Coefficients are stored in little-endian order:\n * coefficients[0] = constant term (x^0)\n * coefficients[1] = linear term (x^1)\n * ...\n */\nexport class Poly {\n coefficients: GF16[];\n\n constructor(coefficients: GF16[]) {\n this.coefficients = coefficients;\n }\n\n /** Create a zero polynomial of a given length. */\n static zeros(len: number): Poly {\n const coeffs: GF16[] = new Array<GF16>(len);\n for (let i = 0; i < len; i++) {\n coeffs[i] = GF16.ZERO;\n }\n return new Poly(coeffs);\n }\n\n /** Number of coefficients. */\n get length(): number {\n return this.coefficients.length;\n }\n\n // -- Evaluation -----------------------------------------------------------\n\n /**\n * Evaluate the polynomial at a given point using a divide-and-conquer\n * approach for computing powers of x, then a dot product.\n *\n * xs[0] = 1, xs[1] = x, xs[i] = xs[floor(i/2)] * xs[floor(i/2) + (i%2)]\n */\n computeAt(x: GF16): GF16 {\n const n = this.coefficients.length;\n if (n === 0) return GF16.ZERO;\n if (n === 1) return this.coefficients[0];\n\n // Build powers of x\n const xs: GF16[] = new Array<GF16>(n);\n xs[0] = GF16.ONE;\n if (n > 1) xs[1] = x;\n\n for (let i = 2; i < n; i++) {\n const half = i >>> 1;\n const rem = i & 1;\n xs[i] = xs[half].mul(xs[half + rem]);\n }\n\n // Dot product: sum(coefficients[i] * xs[i])\n let result = GF16.ZERO;\n for (let i = 0; i < n; i++) {\n result = result.add(this.coefficients[i].mul(xs[i]));\n }\n return result;\n }\n\n // -- In-place arithmetic --------------------------------------------------\n\n /** Add another polynomial to this one in-place. */\n addAssign(other: Poly): void {\n // Extend if necessary\n while (this.coefficients.length < other.coefficients.length) {\n this.coefficients.push(GF16.ZERO);\n }\n for (let i = 0; i < other.coefficients.length; i++) {\n this.coefficients[i] = this.coefficients[i].add(other.coefficients[i]);\n }\n }\n\n /** Multiply all coefficients by a scalar in-place. */\n multAssign(m: GF16): void {\n parallelMult(m, this.coefficients);\n }\n\n // -- Serialization --------------------------------------------------------\n\n /** Serialize coefficients as big-endian u16 pairs. */\n serialize(): Uint8Array {\n const out = new Uint8Array(this.coefficients.length * 2);\n for (let i = 0; i < this.coefficients.length; i++) {\n const v = this.coefficients[i].value;\n out[i * 2] = (v >>> 8) & 0xff;\n out[i * 2 + 1] = v & 0xff;\n }\n return out;\n }\n\n /** Deserialize from big-endian u16 pairs. */\n static deserialize(data: Uint8Array): Poly {\n if (data.length % 2 !== 0) {\n throw new PolynomialError(\"Poly data length must be even\");\n }\n const n = data.length / 2;\n const coeffs: GF16[] = new Array<GF16>(n);\n for (let i = 0; i < n; i++) {\n coeffs[i] = new GF16((data[i * 2] << 8) | data[i * 2 + 1]);\n }\n return new Poly(coeffs);\n }\n\n // -- Lagrange interpolation -----------------------------------------------\n\n /**\n * Lagrange interpolation over a set of points.\n *\n * Given N points (x_i, y_i), produces the unique polynomial of degree < N\n * passing through all of them.\n */\n static lagrangeInterpolate(pts: Pt[]): Poly {\n const n = pts.length;\n if (n === 0) return new Poly([]);\n\n // Step 1: Compute the \"master\" product polynomial\n // P(x) = PRODUCT_{i=0}^{n-1} (x - x_i)\n //\n // In GF(2^n), (x - x_i) = (x + x_i) since subtraction = addition.\n // We represent (x + x_i) as [x_i, 1] (constant, linear).\n let product = new Poly([pts[0].x, GF16.ONE]);\n for (let i = 1; i < n; i++) {\n product = polyMultiply(product, new Poly([pts[i].x, GF16.ONE]));\n }\n\n // Step 2: For each point, compute the Lagrange basis polynomial\n // L_i(x) = y_i * PRODUCT_{j != i} (x - x_j) / PRODUCT_{j != i} (x_i - x_j)\n //\n // We obtain PRODUCT_{j != i} (x - x_j) by dividing the master product by\n // (x - x_i) using synthetic division.\n const result = Poly.zeros(n);\n\n for (let i = 0; i < n; i++) {\n // Synthetic division of `product` by (x - x_i) = (x + x_i)\n const basis = syntheticDivide(product, pts[i].x);\n\n // Compute the denominator: PRODUCT_{j != i} (x_i - x_j)\n // This is just basis.computeAt(x_i) since basis = product / (x - x_i)\n // and product(x_i) = 0, so we evaluate the quotient at x_i.\n const denom = basis.computeAt(pts[i].x);\n\n // Scale: L_i(x) = basis(x) * y_i / denom\n const scale = pts[i].y.div(denom);\n const scaled = clonePoly(basis);\n scaled.multAssign(scale);\n\n result.addAssign(scaled);\n }\n\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Polynomial helpers (private)\n// ---------------------------------------------------------------------------\n\n/** Multiply two polynomials (convolution over GF(2^16)). */\nfunction polyMultiply(a: Poly, b: Poly): Poly {\n if (a.length === 0 || b.length === 0) return new Poly([]);\n const result = Poly.zeros(a.length + b.length - 1);\n for (let i = 0; i < a.length; i++) {\n for (let j = 0; j < b.length; j++) {\n result.coefficients[i + j] = result.coefficients[i + j].add(\n a.coefficients[i].mul(b.coefficients[j]),\n );\n }\n }\n return result;\n}\n\n/**\n * Synthetic division: divide poly by (x - root) = (x + root) in GF(2^n).\n *\n * Returns the quotient polynomial (degree one less than input).\n */\nfunction syntheticDivide(poly: Poly, root: GF16): Poly {\n const n = poly.length;\n if (n <= 1) return new Poly([]);\n\n // Work from high degree down\n const quotient: GF16[] = new Array<GF16>(n - 1);\n let carry = GF16.ZERO;\n\n for (let i = n - 1; i >= 1; i--) {\n const coeff = poly.coefficients[i].add(carry);\n quotient[i - 1] = coeff;\n // In GF(2^n), multiply by root (same as negated root since -root = root)\n carry = coeff.mul(root);\n }\n\n return new Poly(quotient);\n}\n\n/** Clone a polynomial (shallow copy of coefficient array). */\nfunction clonePoly(p: Poly): Poly {\n return new Poly(p.coefficients.slice());\n}\n\n// ---------------------------------------------------------------------------\n// SortedPtSet - maintains points sorted by x.value, no duplicate x's\n// ---------------------------------------------------------------------------\n\nclass SortedPtSet {\n private readonly pts: Pt[] = [];\n\n get length(): number {\n return this.pts.length;\n }\n\n /** Insert a point, maintaining sorted order. Returns false if duplicate x. */\n insert(pt: Pt): boolean {\n const idx = this.findIndex(pt.x.value);\n if (idx < this.pts.length && this.pts[idx].x.value === pt.x.value) {\n return false; // duplicate x\n }\n this.pts.splice(idx, 0, pt);\n return true;\n }\n\n /** Binary search for the insertion point of a given x value. */\n private findIndex(xVal: number): number {\n let lo = 0;\n let hi = this.pts.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (this.pts[mid].x.value < xVal) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n }\n\n /** Look up a point by x value. Returns undefined if not found. */\n findByX(xVal: number): Pt | undefined {\n const idx = this.findIndex(xVal);\n if (idx < this.pts.length && this.pts[idx].x.value === xVal) {\n return this.pts[idx];\n }\n return undefined;\n }\n\n /** Return all points as an array (for interpolation). */\n toArray(): Pt[] {\n return this.pts.slice();\n }\n\n /** Serialize all points as big-endian u16 pairs (x then y). */\n serialize(): Uint8Array {\n const out = new Uint8Array(this.pts.length * 4);\n for (let i = 0; i < this.pts.length; i++) {\n const pt = this.pts[i];\n out[i * 4] = (pt.x.value >>> 8) & 0xff;\n out[i * 4 + 1] = pt.x.value & 0xff;\n out[i * 4 + 2] = (pt.y.value >>> 8) & 0xff;\n out[i * 4 + 3] = pt.y.value & 0xff;\n }\n return out;\n }\n\n /** Deserialize from big-endian u16 pairs (x then y). */\n static deserialize(data: Uint8Array): SortedPtSet {\n if (data.length % 4 !== 0) {\n throw new PolynomialError(\"SortedPtSet data length must be multiple of 4\");\n }\n const set = new SortedPtSet();\n const n = data.length / 4;\n for (let i = 0; i < n; i++) {\n const x = new GF16((data[i * 4] << 8) | data[i * 4 + 1]);\n const y = new GF16((data[i * 4 + 2] << 8) | data[i * 4 + 3]);\n set.insert({ x, y });\n }\n return set;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Encoder state\n// ---------------------------------------------------------------------------\n\n/** Points-based state: raw GF16 values for each of 16 polynomials. */\ninterface PointsState {\n kind: \"points\";\n /** 16 arrays of GF16 y-values (x is implicit: 0, 1, 2, ...). */\n points: GF16[][];\n}\n\n/** Polys-based state: Lagrange-interpolated polynomials. */\ninterface PolysState {\n kind: \"polys\";\n polys: Poly[];\n}\n\ntype EncoderState = PointsState | PolysState;\n\n// ---------------------------------------------------------------------------\n// PolyEncoder\n// ---------------------------------------------------------------------------\n\nexport class PolyEncoder implements Encoder {\n private idx: number;\n private state: EncoderState;\n\n private constructor(idx: number, state: EncoderState) {\n this.idx = idx;\n this.state = state;\n }\n\n /**\n * Create an encoder from a message byte array.\n *\n * The message is split into 16 interleaved streams of GF16 values.\n * Each pair of consecutive bytes becomes one GF16 element. If the message\n * length is odd, it is padded with a zero byte.\n */\n static encodeBytes(msg: Uint8Array): PolyEncoder {\n if (msg.length % 2 !== 0) {\n throw new PolynomialError(\"Message length must be even\");\n }\n if (msg.length > MAX_MESSAGE_LENGTH) {\n throw new PolynomialError(\"Message length exceeds maximum\");\n }\n\n // Total number of GF16 values\n const totalValues = msg.length / 2;\n\n // Initialize 16 point arrays\n const points: GF16[][] = new Array<GF16[]>(NUM_POLYS);\n for (let p = 0; p < NUM_POLYS; p++) {\n points[p] = [];\n }\n\n // Distribute values across 16 polynomials round-robin\n for (let i = 0; i < totalValues; i++) {\n const poly = i % NUM_POLYS;\n const value = (msg[i * 2] << 8) | msg[i * 2 + 1];\n points[poly].push(new GF16(value));\n }\n\n return new PolyEncoder(0, { kind: \"points\", points });\n }\n\n /** Return the next chunk and advance the index. */\n nextChunk(): Chunk {\n const chunk = this.chunkAt(this.idx);\n this.idx++;\n return chunk;\n }\n\n /** Compute the chunk at a specific index. */\n chunkAt(idx: number): Chunk {\n const data = new Uint8Array(CHUNK_DATA_SIZE);\n\n for (let i = 0; i < NUM_POLYS; i++) {\n const totalIdx = idx * NUM_POLYS + i;\n const poly = totalIdx % NUM_POLYS;\n const polyIdx = Math.floor(totalIdx / NUM_POLYS);\n const val = this.pointAt(poly, polyIdx);\n data[i * 2] = (val.value >>> 8) & 0xff;\n data[i * 2 + 1] = val.value & 0xff;\n }\n\n return { index: idx & 0xffff, data };\n }\n\n /**\n * Get the GF16 value for polynomial `poly` at index `idx`.\n *\n * If we are in Points state and the index is within range, return directly.\n * Otherwise, convert to Polys state and evaluate.\n */\n private pointAt(poly: number, idx: number): GF16 {\n if (this.state.kind === \"points\") {\n const pts = this.state.points[poly];\n if (idx < pts.length) {\n return pts[idx];\n }\n // Need to convert to polys for extrapolation\n this.convertToPolys();\n }\n\n // State is now \"polys\"\n const polys = (this.state as PolysState).polys;\n return polys[poly].computeAt(new GF16(idx));\n }\n\n /** Convert from Points state to Polys state via Lagrange interpolation. */\n private convertToPolys(): void {\n if (this.state.kind === \"polys\") return;\n\n const { points } = this.state;\n const polys: Poly[] = new Array<Poly>(NUM_POLYS);\n\n for (let p = 0; p < NUM_POLYS; p++) {\n const pts: Pt[] = points[p].map((y, i) => ({\n x: new GF16(i),\n y,\n }));\n polys[p] = Poly.lagrangeInterpolate(pts);\n }\n\n this.state = { kind: \"polys\", polys };\n }\n\n /** Serialize encoder state for protobuf transport. */\n toProto(): { idx: number; pts: Uint8Array[]; polys: Uint8Array[] } {\n if (this.state.kind === \"points\") {\n const pts: Uint8Array[] = this.state.points.map((arr) => {\n const buf = new Uint8Array(arr.length * 2);\n for (let i = 0; i < arr.length; i++) {\n buf[i * 2] = (arr[i].value >>> 8) & 0xff;\n buf[i * 2 + 1] = arr[i].value & 0xff;\n }\n return buf;\n });\n return { idx: this.idx, pts, polys: [] };\n }\n const polys: Uint8Array[] = this.state.polys.map((p) => p.serialize());\n return { idx: this.idx, pts: [], polys };\n }\n\n /** Restore encoder from protobuf data. */\n static fromProto(data: { idx: number; pts: Uint8Array[]; polys: Uint8Array[] }): PolyEncoder {\n if (data.polys.length > 0) {\n const polys = data.polys.map((buf) => Poly.deserialize(buf));\n return new PolyEncoder(data.idx, { kind: \"polys\", polys });\n }\n const points: GF16[][] = data.pts.map((buf) => {\n const arr: GF16[] = [];\n for (let i = 0; i < buf.length; i += 2) {\n arr.push(new GF16((buf[i] << 8) | buf[i + 1]));\n }\n return arr;\n });\n return new PolyEncoder(data.idx, { kind: \"points\", points });\n }\n}\n\n// ---------------------------------------------------------------------------\n// PolyDecoder\n// ---------------------------------------------------------------------------\n\nexport class PolyDecoder implements Decoder {\n /** Total number of GF16 values needed (= message byte length / 2, rounded up). */\n ptsNeeded: number;\n private readonly pts: SortedPtSet[];\n private _isComplete: boolean;\n\n private constructor(ptsNeeded: number, pts: SortedPtSet[], isComplete: boolean) {\n this.ptsNeeded = ptsNeeded;\n this.pts = pts;\n this._isComplete = isComplete;\n }\n\n /**\n * Create a decoder for a message of `lenBytes` bytes.\n *\n * The caller must know the original message length to know when enough\n * chunks have been received.\n */\n static create(lenBytes: number): PolyDecoder {\n if (lenBytes % 2 !== 0) {\n throw new PolynomialError(\"Message length must be even\");\n }\n const ptsNeeded = lenBytes / 2;\n\n const pts: SortedPtSet[] = new Array<SortedPtSet>(NUM_POLYS);\n for (let i = 0; i < NUM_POLYS; i++) {\n pts[i] = new SortedPtSet();\n }\n\n return new PolyDecoder(ptsNeeded, pts, false);\n }\n\n /** Whether all polynomial sets have enough points to decode. */\n get isComplete(): boolean {\n return this._isComplete;\n }\n\n /**\n * Number of points necessary for polynomial `poly`.\n *\n * The total points (ptsNeeded) are distributed across 16 polynomials\n * round-robin, so some may need one more point than others.\n */\n private necessaryPoints(poly: number): number {\n const base = Math.floor(this.ptsNeeded / NUM_POLYS);\n return poly < this.ptsNeeded % NUM_POLYS ? base + 1 : base;\n }\n\n /** Add a chunk to the decoder. */\n addChunk(chunk: Chunk): void {\n if (this._isComplete) return;\n\n for (let i = 0; i < NUM_POLYS; i++) {\n const totalIdx = chunk.index * NUM_POLYS + i;\n const poly = totalIdx % NUM_POLYS;\n const polyIdx = Math.floor(totalIdx / NUM_POLYS);\n\n const needed = this.necessaryPoints(poly);\n if (this.pts[poly].length >= needed) {\n continue; // Already have enough points for this polynomial\n }\n\n const y = new GF16((chunk.data[i * 2] << 8) | chunk.data[i * 2 + 1]);\n const pt: Pt = { x: new GF16(polyIdx), y };\n this.pts[poly].insert(pt);\n }\n\n // Check completeness\n this._isComplete = this.checkComplete();\n }\n\n /** Check whether all 16 polynomial sets have enough points. */\n private checkComplete(): boolean {\n for (let p = 0; p < NUM_POLYS; p++) {\n if (this.pts[p].length < this.necessaryPoints(p)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Attempt to decode the message.\n *\n * Returns the decoded byte array if enough chunks have been received,\n * or null if more chunks are needed.\n */\n decodedMessage(): Uint8Array | null {\n if (!this._isComplete) return null;\n\n const result = new Uint8Array(this.ptsNeeded * 2);\n\n for (let i = 0; i < this.ptsNeeded; i++) {\n const poly = i % NUM_POLYS;\n const polyIdx = Math.floor(i / NUM_POLYS);\n const xVal = polyIdx;\n\n // Try direct lookup first (fast path)\n let val: GF16;\n const direct = this.pts[poly].findByX(xVal);\n if (direct !== undefined) {\n val = direct.y;\n } else {\n // Fall back to Lagrange interpolation\n const allPts = this.pts[poly].toArray();\n const interpolated = Poly.lagrangeInterpolate(allPts);\n val = interpolated.computeAt(new GF16(xVal));\n }\n\n result[i * 2] = (val.value >>> 8) & 0xff;\n result[i * 2 + 1] = val.value & 0xff;\n }\n\n return result;\n }\n\n /** Serialize decoder state for protobuf transport. */\n toProto(): {\n ptsNeeded: number;\n polys: number;\n pts: Uint8Array[];\n isComplete: boolean;\n } {\n return {\n ptsNeeded: this.ptsNeeded,\n polys: NUM_POLYS,\n pts: this.pts.map((s) => s.serialize()),\n isComplete: this._isComplete,\n };\n }\n\n /** Restore decoder from protobuf data. */\n static fromProto(data: {\n ptsNeeded: number;\n polys: number;\n pts: Uint8Array[];\n isComplete: boolean;\n }): PolyDecoder {\n const pts: SortedPtSet[] = data.pts.map((buf) => SortedPtSet.deserialize(buf));\n // Ensure we always have exactly 16 sets\n while (pts.length < NUM_POLYS) {\n pts.push(new SortedPtSet() as unknown as SortedPtSet);\n }\n return new PolyDecoder(data.ptsNeeded, pts, data.isComplete);\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * SPQR Authenticator -- HMAC-SHA256 MAC for KEM exchanges.\n *\n * Ported from Signal's spqr crate: authenticator.rs\n *\n * The Authenticator produces and verifies MACs over ciphertext and header\n * data using HMAC-SHA256. The internal rootKey and macKey are updated\n * via HKDF at each epoch transition.\n *\n * All info strings and data formats MUST match the Rust implementation exactly.\n */\n\nimport { hkdfSha256, hmacSha256 } from \"./kdf.js\";\nimport { concat, bigintToBE8, constantTimeEqual } from \"./util.js\";\nimport {\n ZERO_SALT,\n MAC_SIZE,\n LABEL_AUTH_UPDATE,\n LABEL_CT_MAC,\n LABEL_HDR_MAC,\n} from \"./constants.js\";\nimport { AuthenticatorError } from \"./error.js\";\nimport type { Epoch } from \"./types.js\";\nimport type { PbAuthenticator } from \"./proto/pq-ratchet-types.js\";\n\n// Pre-encode label strings\nconst enc = new TextEncoder();\nconst AUTH_UPDATE_INFO = enc.encode(LABEL_AUTH_UPDATE);\nconst CT_MAC_PREFIX = enc.encode(LABEL_CT_MAC);\nconst HDR_MAC_PREFIX = enc.encode(LABEL_HDR_MAC);\n\nexport { MAC_SIZE };\n\n/**\n * Authenticator manages root_key and mac_key state for producing\n * and verifying MACs over KEM ciphertext and headers.\n *\n * The update operation uses HKDF:\n * IKM = [rootKey || key]\n * Salt = ZERO_SALT (32 zeros)\n * Info = LABEL_AUTH_UPDATE + epoch_be8\n * Output: 64 bytes -> [0..32] = new rootKey, [32..64] = new macKey\n *\n * MAC operations use HMAC-SHA256:\n * Key = macKey\n * Data = [label_prefix || epoch_be8 || payload]\n */\nexport class Authenticator {\n private rootKey: Uint8Array;\n private macKey: Uint8Array;\n\n constructor(rootKey: Uint8Array, macKey: Uint8Array) {\n this.rootKey = rootKey;\n this.macKey = macKey;\n }\n\n /**\n * Create a new Authenticator from a root key and initial epoch.\n * Matches Rust: `Authenticator::new(root_key, ep)`\n *\n * Initializes with zero keys, then immediately updates with\n * the provided root key and epoch.\n */\n static create(rootKey: Uint8Array, epoch: Epoch): Authenticator {\n const auth = new Authenticator(new Uint8Array(32), new Uint8Array(32));\n auth.update(epoch, rootKey);\n return auth;\n }\n\n /**\n * Update the authenticator with a new epoch and key material.\n *\n * HKDF(IKM=[rootKey||key], salt=ZERO_SALT, info=[label||epoch_be8], length=64)\n *\n * Output split: rootKey = [0..32], macKey = [32..64]\n */\n update(epoch: Epoch, key: Uint8Array): void {\n // ikm = [root_key || key]\n const ikm = concat(this.rootKey, key);\n\n const epochBe8 = bigintToBE8(epoch);\n const info = concat(AUTH_UPDATE_INFO, epochBe8);\n\n const derived = hkdfSha256(ikm, ZERO_SALT, info, 64);\n this.rootKey = derived.slice(0, 32);\n this.macKey = derived.slice(32, 64);\n }\n\n /**\n * Compute MAC over ciphertext.\n *\n * HMAC-SHA256(macKey, [LABEL_CT_MAC || epoch_be8 || ct])\n */\n macCt(epoch: Epoch, ct: Uint8Array): Uint8Array {\n const epochBe8 = bigintToBE8(epoch);\n const data = concat(CT_MAC_PREFIX, epochBe8, ct);\n return hmacSha256(this.macKey, data);\n }\n\n /**\n * Verify ciphertext MAC (constant-time comparison).\n * Throws AuthenticatorError if the MAC does not match.\n */\n verifyCt(epoch: Epoch, ct: Uint8Array, expectedMac: Uint8Array): void {\n const computed = this.macCt(epoch, ct);\n if (!constantTimeEqual(computed, expectedMac)) {\n throw new AuthenticatorError(\"Ciphertext MAC is invalid\", \"INVALID_CT_MAC\");\n }\n }\n\n /**\n * Compute MAC over header (encapsulation key header).\n *\n * HMAC-SHA256(macKey, [LABEL_HDR_MAC || epoch_be8 || hdr])\n */\n macHdr(epoch: Epoch, hdr: Uint8Array): Uint8Array {\n const epochBe8 = bigintToBE8(epoch);\n const data = concat(HDR_MAC_PREFIX, epochBe8, hdr);\n return hmacSha256(this.macKey, data);\n }\n\n /**\n * Verify header MAC (constant-time comparison).\n * Throws AuthenticatorError if the MAC does not match.\n */\n verifyHdr(epoch: Epoch, hdr: Uint8Array, expectedMac: Uint8Array): void {\n const computed = this.macHdr(epoch, hdr);\n if (!constantTimeEqual(computed, expectedMac)) {\n throw new AuthenticatorError(\"Encapsulation key MAC is invalid\", \"INVALID_HDR_MAC\");\n }\n }\n\n /**\n * Deep clone this authenticator.\n */\n clone(): Authenticator {\n return new Authenticator(Uint8Array.from(this.rootKey), Uint8Array.from(this.macKey));\n }\n\n // ---- Protobuf serialization ----\n\n /**\n * Serialize to protobuf representation.\n * Matches Rust Authenticator::into_pb().\n */\n toProto(): PbAuthenticator {\n return {\n rootKey: Uint8Array.from(this.rootKey),\n macKey: Uint8Array.from(this.macKey),\n };\n }\n\n /**\n * Deserialize from protobuf representation.\n * Matches Rust Authenticator::from_pb().\n */\n static fromProto(pb: PbAuthenticator): Authenticator {\n return new Authenticator(Uint8Array.from(pb.rootKey), Uint8Array.from(pb.macKey));\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Chunked send_ek state machine for SPQR V1.\n *\n * Wraps the unchunked send_ek states with PolyEncoder/PolyDecoder erasure\n * coding, enabling chunk-by-chunk data transfer.\n *\n * States:\n * KeysUnsampled -- sendHdrChunk(rng) --> KeysSampled + Chunk\n * KeysSampled -- sendHdrChunk() --> KeysSampled + Chunk\n * -- recvCt1Chunk(epoch, chunk) --> HeaderSent\n * HeaderSent -- sendEkChunk() --> HeaderSent + Chunk\n * -- recvCt1Chunk(epoch, chunk) --> HeaderSent | Ct1Received\n * Ct1Received -- sendEkChunk() --> Ct1Received + Chunk\n * -- recvCt2Chunk(epoch, chunk) --> EkSentCt1Received\n * EkSentCt1Received -- recvCt2Chunk(epoch, chunk) --> EkSentCt1Received | sendCt.NoHeaderReceived\n */\n\nimport type * as unchunked from \"../unchunked/send-ek.js\";\nimport * as unchunkedSendCt from \"../unchunked/send-ct.js\";\nimport { PolyEncoder, PolyDecoder } from \"../../encoding/polynomial.js\";\nimport type { Chunk } from \"../../encoding/polynomial.js\";\nimport { HEADER_SIZE, CT1_SIZE, CT2_SIZE } from \"../../incremental-mlkem768.js\";\nimport { MAC_SIZE } from \"../../authenticator.js\";\nimport { concat } from \"../../util.js\";\nimport { SpqrError, SpqrErrorCode } from \"../../error.js\";\nimport type { Epoch, EpochSecret, RandomBytes } from \"../../types.js\";\nimport type * as sendCt from \"./send-ct.js\";\n\n// ---------------------------------------------------------------------------\n// Discriminated union result types\n// ---------------------------------------------------------------------------\n\nexport type HeaderSentRecvChunk =\n | { done: false; state: HeaderSent }\n | { done: true; state: Ct1Received };\n\nexport type EkSentCt1ReceivedRecvChunk =\n | { done: false; state: EkSentCt1Received }\n | { done: true; state: sendCt.NoHeaderReceived; epochSecret: EpochSecret };\n\n// ---------------------------------------------------------------------------\n// State 1: KeysUnsampled\n// ---------------------------------------------------------------------------\n\n/**\n * Initial chunked send_ek state. No keypair generated yet.\n * Wraps unchunked.KeysUnsampled.\n */\nexport class KeysUnsampled {\n constructor(public readonly uc: unchunked.KeysUnsampled) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /**\n * Generate keypair, produce header + MAC, encode into PolyEncoder,\n * and return the first header chunk.\n */\n sendHdrChunk(rng: RandomBytes): [KeysSampled, Chunk] {\n const [headerSent, hdr, mac] = this.uc.sendHeader(rng);\n const hdrPayload = concat(hdr, mac);\n const sendingHdr = PolyEncoder.encodeBytes(hdrPayload);\n const chunk = sendingHdr.nextChunk();\n return [new KeysSampled(headerSent, sendingHdr), chunk];\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 2: KeysSampled\n// ---------------------------------------------------------------------------\n\n/**\n * Header has been generated and encoding started. Still sending header chunks.\n * Can also begin receiving ct1 chunks.\n */\nexport class KeysSampled {\n constructor(\n public readonly uc: unchunked.HeaderSent,\n public readonly sendingHdr: PolyEncoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next header chunk. */\n sendHdrChunk(): [KeysSampled, Chunk] {\n const chunk = this.sendingHdr.nextChunk();\n return [this, chunk];\n }\n\n /**\n * Receive a ct1 chunk from the send_ct peer.\n * This triggers sending the encapsulation key.\n */\n recvCt1Chunk(epoch: Epoch, chunk: Chunk): HeaderSent {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n // Create ct1 decoder\n const receivingCt1 = PolyDecoder.create(CT1_SIZE);\n receivingCt1.addChunk(chunk);\n\n // Transition unchunked: send ek\n const [ekSent, ek] = this.uc.sendEk();\n const sendingEk = PolyEncoder.encodeBytes(ek);\n\n return new HeaderSent(ekSent, sendingEk, receivingCt1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 3: HeaderSent\n// ---------------------------------------------------------------------------\n\n/**\n * Sending ek chunks while receiving ct1 chunks.\n */\nexport class HeaderSent {\n constructor(\n public readonly uc: unchunked.EkSent,\n public readonly sendingEk: PolyEncoder,\n public readonly receivingCt1: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next ek chunk. */\n sendEkChunk(): [HeaderSent, Chunk] {\n const chunk = this.sendingEk.nextChunk();\n return [this, chunk];\n }\n\n /** Receive a ct1 chunk. Returns done when ct1 is fully decoded. */\n recvCt1Chunk(epoch: Epoch, chunk: Chunk): HeaderSentRecvChunk {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n this.receivingCt1.addChunk(chunk);\n const decoded = this.receivingCt1.decodedMessage();\n\n if (decoded !== null) {\n // ct1 fully received -- transition unchunked\n const ucResult = this.uc.recvCt1(decoded);\n return { done: true, state: new Ct1Received(ucResult, this.sendingEk) };\n }\n\n return { done: false, state: this };\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 4: Ct1Received\n// ---------------------------------------------------------------------------\n\n/**\n * ct1 has been fully decoded. Still sending ek chunks.\n * Can begin receiving ct2 chunks.\n */\nexport class Ct1Received {\n constructor(\n public readonly uc: unchunked.EkSentCt1Received,\n public readonly sendingEk: PolyEncoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next ek chunk. */\n sendEkChunk(): [Ct1Received, Chunk] {\n const chunk = this.sendingEk.nextChunk();\n return [this, chunk];\n }\n\n /**\n * Receive a ct2 chunk. Creates the ct2 decoder.\n * ct2 payload is CT2_SIZE + MAC_SIZE = 160 bytes\n * (carries ct2 + mac).\n */\n recvCt2Chunk(epoch: Epoch, chunk: Chunk): EkSentCt1Received {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n const receivingCt2 = PolyDecoder.create(CT2_SIZE + MAC_SIZE);\n receivingCt2.addChunk(chunk);\n\n return new EkSentCt1Received(this.uc, receivingCt2);\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 5: EkSentCt1Received\n// ---------------------------------------------------------------------------\n\n/**\n * Both ek sending and ct1 receiving are done. Now receiving ct2 chunks.\n * When ct2 is fully decoded, extract ct2 and mac, then perform decapsulation\n * to derive the epoch secret.\n */\nexport class EkSentCt1Received {\n constructor(\n public readonly uc: unchunked.EkSentCt1Received,\n public readonly receivingCt2: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /**\n * Receive a ct2 chunk. Returns done when ct2 is fully decoded and\n * epoch secret is derived.\n */\n recvCt2Chunk(epoch: Epoch, chunk: Chunk): EkSentCt1ReceivedRecvChunk {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n this.receivingCt2.addChunk(chunk);\n const decoded = this.receivingCt2.decodedMessage();\n\n if (decoded !== null) {\n // Split the 160-byte payload: ct2(128) + mac(32)\n const ct2 = decoded.slice(0, CT2_SIZE);\n const mac = decoded.slice(CT2_SIZE);\n\n // Use the unchunked state directly (ct1 is already the REAL ct1)\n const result = this.uc.recvCt2(ct2, mac);\n\n // Construct the next-epoch send_ct NoHeaderReceived state\n const nextUcSendCt = new unchunkedSendCt.NoHeaderReceived(result.nextEpoch, result.auth);\n const receivingHdr = PolyDecoder.create(HEADER_SIZE + MAC_SIZE);\n\n return {\n done: true,\n state: createSendCtNoHeaderReceived(nextUcSendCt, receivingHdr),\n epochSecret: result.epochSecret,\n };\n }\n\n return { done: false, state: this };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory for creating send-ct NoHeaderReceived (breaks circular dependency)\n// ---------------------------------------------------------------------------\n\n/** @internal Set by the chunked index module to break circular imports. */\nlet createSendCtNoHeaderReceived: (\n uc: unchunkedSendCt.NoHeaderReceived,\n receivingHdr: PolyDecoder,\n) => sendCt.NoHeaderReceived;\n\n/** @internal Called by the index module to wire up the factory. */\nexport function _setCreateSendCtNoHeaderReceived(\n factory: (\n uc: unchunkedSendCt.NoHeaderReceived,\n receivingHdr: PolyDecoder,\n ) => sendCt.NoHeaderReceived,\n): void {\n createSendCtNoHeaderReceived = factory;\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Unchunked send_ek state machine for SPQR V1.\n *\n * Ported from Signal's spqr crate: v1/unchunked/send_ek.rs\n *\n * The send_ek side generates an ML-KEM-768 keypair, sends the public key\n * header (hdr) and encapsulation key (ek), then receives ct1 and ct2 from\n * the send_ct peer. On receiving ct2, it performs decapsulation to derive\n * the shared epoch secret.\n *\n * State transitions:\n * KeysUnsampled --sendHeader(rng)--> HeaderSent + (hdr, mac)\n * HeaderSent --sendEk()---------> EkSent + ek\n * EkSent --recvCt1(ct1)-----> EkSentCt1Received\n * EkSentCt1Received --recvCt2(ct2, mac)--> RecvCt2Result (epoch, auth, epochSecret)\n *\n * The caller is responsible for constructing the next-epoch send_ct state\n * (NoHeaderReceived) from the RecvCt2Result, avoiding circular imports.\n */\n\nimport { type Authenticator } from \"../../authenticator.js\";\nimport { hkdfSha256 } from \"../../kdf.js\";\nimport { concat, bigintToBE8 } from \"../../util.js\";\nimport { ZERO_SALT, LABEL_SCKA_KEY } from \"../../constants.js\";\nimport { generate, decaps } from \"../../incremental-mlkem768.js\";\nimport type { Epoch, EpochSecret, RandomBytes } from \"../../types.js\";\n\n// Pre-encode the SCKA label\nconst SCKA_KEY_LABEL = new TextEncoder().encode(LABEL_SCKA_KEY);\n\n/**\n * Derive the epoch secret from the KEM shared secret.\n *\n * HKDF-SHA256(ikm=sharedSecret, salt=ZERO_SALT,\n * info=LABEL_SCKA_KEY || epoch_be8, length=32)\n *\n * Matches Rust: info = [b\"Signal_PQCKA_V1_MLKEM768:SCKA Key\", epoch.to_be_bytes()].concat()\n */\nfunction deriveEpochSecret(epoch: Epoch, sharedSecret: Uint8Array): EpochSecret {\n const info = concat(SCKA_KEY_LABEL, bigintToBE8(epoch));\n const secret = hkdfSha256(sharedSecret, ZERO_SALT, info, 32);\n return { epoch, secret };\n}\n\n/** Result of EkSentCt1Received.recvCt2 */\nexport interface RecvCt2Result {\n /** The next epoch (current + 1) */\n nextEpoch: Epoch;\n /** The updated authenticator for the next epoch */\n auth: Authenticator;\n /** The derived epoch secret for chain advancement */\n epochSecret: EpochSecret;\n}\n\n// ---- State: KeysUnsampled ----\n\n/**\n * Initial send_ek state. No keypair has been generated yet.\n */\nexport class KeysUnsampled {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n ) {}\n\n /**\n * Generate an ML-KEM-768 keypair and produce the header + MAC.\n *\n * @param rng - Random byte generator\n * @returns [nextState, hdr, hdrMac]\n */\n sendHeader(rng: RandomBytes): [HeaderSent, Uint8Array, Uint8Array] {\n const keys = generate(rng);\n const mac = this.auth.macHdr(this.epoch, keys.hdr);\n\n const nextState = new HeaderSent(this.epoch, this.auth, keys.ek, keys.dk);\n\n return [nextState, keys.hdr, mac];\n }\n}\n\n// ---- State: HeaderSent ----\n\n/**\n * The header has been sent to the peer. Ready to send the encapsulation key.\n */\nexport class HeaderSent {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly ek: Uint8Array,\n public readonly dk: Uint8Array,\n ) {}\n\n /**\n * Produce the encapsulation key to send to the peer.\n *\n * @returns [nextState, ek]\n */\n sendEk(): [EkSent, Uint8Array] {\n const nextState = new EkSent(this.epoch, this.auth, this.dk);\n return [nextState, this.ek];\n }\n}\n\n// ---- State: EkSent ----\n\n/**\n * Both the header and encapsulation key have been sent.\n * Waiting to receive ct1 from the send_ct peer.\n */\nexport class EkSent {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly dk: Uint8Array,\n ) {}\n\n /**\n * Receive the first ciphertext fragment from the peer.\n *\n * @param ct1 - The 960-byte first ciphertext fragment\n * @returns Next state\n */\n recvCt1(ct1: Uint8Array): EkSentCt1Received {\n return new EkSentCt1Received(this.epoch, this.auth, this.dk, ct1);\n }\n}\n\n// ---- State: EkSentCt1Received ----\n\n/**\n * ct1 has been received. Waiting for ct2 to complete decapsulation.\n */\nexport class EkSentCt1Received {\n constructor(\n public readonly epoch: Epoch,\n public readonly auth: Authenticator,\n public readonly dk: Uint8Array,\n public readonly ct1: Uint8Array,\n ) {}\n\n /**\n * Receive ct2 and MAC, perform decapsulation, verify the MAC,\n * and derive the epoch secret.\n *\n * The caller constructs the next send_ct::NoHeaderReceived state from\n * the returned nextEpoch and auth.\n *\n * @param ct2 - The 128-byte second ciphertext fragment\n * @param mac - The 32-byte HMAC-SHA256 MAC over the full ciphertext\n * @returns Result containing next epoch, updated auth, and epoch secret\n * @throws {AuthenticatorError} If the ciphertext MAC is invalid\n */\n recvCt2(ct2: Uint8Array, mac: Uint8Array): RecvCt2Result {\n // Decapsulate to recover shared secret\n const sharedSecret = decaps(this.dk, this.ct1, ct2);\n\n // Derive epoch secret (with epoch in HKDF info, matching Rust)\n const epochSecret = deriveEpochSecret(this.epoch, sharedSecret);\n\n // Update authenticator with the HKDF-derived secret at current epoch\n const auth = this.auth.clone();\n auth.update(this.epoch, epochSecret.secret);\n\n // Verify the ciphertext MAC: MAC over ct1 || ct2\n const fullCt = concat(this.ct1, ct2);\n auth.verifyCt(this.epoch, fullCt, mac);\n\n const nextEpoch = this.epoch + 1n;\n\n return { nextEpoch, auth, epochSecret };\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Chunked send_ct state machine for SPQR V1.\n *\n * Wraps the unchunked send_ct states with PolyEncoder/PolyDecoder erasure\n * coding, enabling chunk-by-chunk data transfer.\n *\n * True incremental ML-KEM (Phase 9):\n * - send_ct produces REAL ct1 chunks from the start.\n * - ct2 payload carries only ct2(128) + mac(32) = 160 bytes.\n * - Epoch secret is derived in sendCt1 (when encaps1 is performed).\n *\n * States:\n * NoHeaderReceived -- recvHdrChunk(epoch, chunk) --> NoHeaderReceived | HeaderReceived\n * HeaderReceived -- sendCt1Chunk(rng) --> [Ct1Sampled, Chunk, EpochSecret]\n * Ct1Sampled -- sendCt1Chunk() --> [Ct1Sampled, Chunk]\n * -- recvEkChunk(epoch, chunk, ct1Ack) --> 4 outcomes\n * EkReceivedCt1Sampled -- sendCt1Chunk() --> [EkReceivedCt1Sampled, Chunk]\n * -- recvCt1Ack(epoch) --> Ct2Sampled\n * Ct1Acknowledged -- recvEkChunk(epoch, chunk) --> Ct1Acknowledged | Ct2Sampled\n * Ct2Sampled -- sendCt2Chunk() --> [Ct2Sampled, Chunk]\n * -- recvNextEpoch(epoch) --> sendEk.KeysUnsampled\n */\n\nimport * as unchunkedSendCt from \"../unchunked/send-ct.js\";\nimport * as unchunkedSendEk from \"../unchunked/send-ek.js\";\nimport { PolyEncoder, PolyDecoder } from \"../../encoding/polynomial.js\";\nimport type { Chunk } from \"../../encoding/polynomial.js\";\nimport { HEADER_SIZE, EK_SIZE } from \"../../incremental-mlkem768.js\";\nimport { MAC_SIZE } from \"../../authenticator.js\";\nimport { Authenticator } from \"../../authenticator.js\";\nimport { concat } from \"../../util.js\";\nimport { SpqrError, SpqrErrorCode } from \"../../error.js\";\nimport type { Epoch, EpochSecret, RandomBytes } from \"../../types.js\";\nimport * as sendEk from \"./send-ek.js\";\n\n// ---------------------------------------------------------------------------\n// Discriminated union result types\n// ---------------------------------------------------------------------------\n\nexport type NoHeaderReceivedRecvChunk =\n | { done: false; state: NoHeaderReceived }\n | { done: true; state: HeaderReceived };\n\nexport type Ct1SampledRecvChunk =\n | { tag: \"stillReceivingStillSending\"; state: Ct1Sampled }\n | { tag: \"stillReceiving\"; state: Ct1Acknowledged }\n | { tag: \"stillSending\"; state: EkReceivedCt1Sampled; epochSecret: EpochSecret | null }\n | { tag: \"done\"; state: Ct2Sampled; epochSecret: EpochSecret | null };\n\nexport type Ct1AcknowledgedRecvChunk =\n | { done: false; state: Ct1Acknowledged }\n | { done: true; state: Ct2Sampled; epochSecret: EpochSecret | null };\n\n// ---------------------------------------------------------------------------\n// State 1: NoHeaderReceived\n// ---------------------------------------------------------------------------\n\n/**\n * Waiting to receive header chunks from the send_ek peer.\n */\nexport class NoHeaderReceived {\n constructor(\n public readonly uc: unchunkedSendCt.NoHeaderReceived,\n public readonly receivingHdr: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /**\n * Create the initial NoHeaderReceived from an auth key.\n */\n static create(authKey: Uint8Array): NoHeaderReceived {\n const auth = Authenticator.create(authKey, 1n);\n const uc = new unchunkedSendCt.NoHeaderReceived(1n, auth);\n const receivingHdr = PolyDecoder.create(HEADER_SIZE + MAC_SIZE);\n return new NoHeaderReceived(uc, receivingHdr);\n }\n\n /** Receive a header chunk. Returns done when header is fully decoded. */\n recvHdrChunk(epoch: Epoch, chunk: Chunk): NoHeaderReceivedRecvChunk {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n this.receivingHdr.addChunk(chunk);\n const decoded = this.receivingHdr.decodedMessage();\n\n if (decoded !== null) {\n // Split: hdr(64) + mac(32)\n const hdr = decoded.slice(0, HEADER_SIZE);\n const mac = decoded.slice(HEADER_SIZE);\n\n // Verify header MAC and transition\n const ucResult = this.uc.recvHeader(epoch, hdr, mac);\n\n // Create ek decoder\n const receivingEk = PolyDecoder.create(EK_SIZE);\n\n return { done: true, state: new HeaderReceived(ucResult, receivingEk) };\n }\n\n return { done: false, state: this };\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 2: HeaderReceived\n// ---------------------------------------------------------------------------\n\n/**\n * Header has been received and verified. Ready to produce ct1 chunks.\n */\nexport class HeaderReceived {\n constructor(\n public readonly uc: unchunkedSendCt.HeaderReceived,\n public readonly receivingEk: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /**\n * Generate encapsulation randomness, produce REAL ct1, encode it,\n * and return the first ct1 chunk.\n *\n * Returns [Ct1Sampled, Chunk, EpochSecret] -- real epoch secret.\n */\n sendCt1Chunk(rng: RandomBytes): [Ct1Sampled, Chunk, EpochSecret] {\n const [ct1Sent, realCt1, epochSecret] = this.uc.sendCt1(rng);\n const sendingCt1 = PolyEncoder.encodeBytes(realCt1);\n const chunk = sendingCt1.nextChunk();\n return [new Ct1Sampled(ct1Sent, sendingCt1, this.receivingEk), chunk, epochSecret];\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 3: Ct1Sampled\n// ---------------------------------------------------------------------------\n\n/**\n * Real ct1 has been produced and encoding started.\n * Sending ct1 chunks while receiving ek chunks.\n */\nexport class Ct1Sampled {\n constructor(\n public readonly uc: unchunkedSendCt.Ct1Sent,\n public readonly sendingCt1: PolyEncoder,\n public readonly receivingEk: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next ct1 chunk. */\n sendCt1Chunk(): [Ct1Sampled, Chunk] {\n const chunk = this.sendingCt1.nextChunk();\n return [this, chunk];\n }\n\n /**\n * Receive an ek chunk, with optional ct1 acknowledgement from peer.\n *\n * Four possible outcomes depending on whether ek is complete and\n * whether the peer acknowledged ct1:\n * - Both: done (Ct2Sampled + epochSecret)\n * - ek complete, no ack: stillSending (EkReceivedCt1Sampled + epochSecret)\n * - ek incomplete, ack: stillReceiving (Ct1Acknowledged)\n * - Neither: stillReceivingStillSending (Ct1Sampled)\n */\n recvEkChunk(epoch: Epoch, chunk: Chunk, ct1Ack: boolean): Ct1SampledRecvChunk {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n this.receivingEk.addChunk(chunk);\n const ekDecoded = this.receivingEk.decodedMessage();\n\n if (ekDecoded !== null && ct1Ack) {\n // Both ek complete and ct1 acknowledged\n const ucResult = this.uc.recvEk(ekDecoded);\n const { state: ct2SentUc, ct2, mac } = ucResult.sendCt2();\n // ct2 payload = ct2(128) + mac(32) = 160 bytes\n const ct2Payload = concat(ct2, mac);\n const sendingCt2 = PolyEncoder.encodeBytes(ct2Payload);\n return {\n tag: \"done\",\n state: new Ct2Sampled(ct2SentUc, sendingCt2),\n epochSecret: null, // Epoch secret already derived in sendCt1\n };\n }\n\n if (ekDecoded !== null && !ct1Ack) {\n // ek complete but ct1 not yet acknowledged\n const ucResult = this.uc.recvEk(ekDecoded);\n return {\n tag: \"stillSending\",\n state: new EkReceivedCt1Sampled(ucResult, this.sendingCt1),\n epochSecret: null, // Epoch secret already derived in sendCt1\n };\n }\n\n if (ekDecoded === null && ct1Ack) {\n // ct1 acknowledged but ek not yet complete\n return {\n tag: \"stillReceiving\",\n state: new Ct1Acknowledged(this.uc, this.receivingEk),\n };\n }\n\n // Neither complete\n return {\n tag: \"stillReceivingStillSending\",\n state: this,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 4: EkReceivedCt1Sampled\n// ---------------------------------------------------------------------------\n\n/**\n * ek has been received and validated.\n * Still sending ct1 chunks, waiting for ct1 acknowledgement.\n */\nexport class EkReceivedCt1Sampled {\n constructor(\n public readonly uc: unchunkedSendCt.Ct1SentEkReceived,\n public readonly sendingCt1: PolyEncoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next ct1 chunk. */\n sendCt1Chunk(): [EkReceivedCt1Sampled, Chunk] {\n const chunk = this.sendingCt1.nextChunk();\n return [this, chunk];\n }\n\n /** Peer has acknowledged ct1. Produce ct2 and encode it. */\n recvCt1Ack(epoch: Epoch): Ct2Sampled {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n const { state: ct2SentUc, ct2, mac } = this.uc.sendCt2();\n // ct2 payload = ct2(128) + mac(32) = 160 bytes\n const ct2Payload = concat(ct2, mac);\n const sendingCt2 = PolyEncoder.encodeBytes(ct2Payload);\n\n return new Ct2Sampled(ct2SentUc, sendingCt2);\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 5: Ct1Acknowledged\n// ---------------------------------------------------------------------------\n\n/**\n * ct1 has been acknowledged by the peer. Still receiving ek chunks.\n * When ek arrives, validate it and produce ct2.\n */\nexport class Ct1Acknowledged {\n constructor(\n public readonly uc: unchunkedSendCt.Ct1Sent,\n public readonly receivingEk: PolyDecoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Receive an ek chunk. Returns done when ek is fully decoded. */\n recvEkChunk(epoch: Epoch, chunk: Chunk): Ct1AcknowledgedRecvChunk {\n if (epoch !== this.uc.epoch) {\n throw new SpqrError(\n `Epoch mismatch: expected ${this.uc.epoch}, got ${epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n this.receivingEk.addChunk(chunk);\n const decoded = this.receivingEk.decodedMessage();\n\n if (decoded !== null) {\n const ucResult = this.uc.recvEk(decoded);\n const { state: ct2SentUc, ct2, mac } = ucResult.sendCt2();\n // ct2 payload = ct2(128) + mac(32) = 160 bytes\n const ct2Payload = concat(ct2, mac);\n const sendingCt2 = PolyEncoder.encodeBytes(ct2Payload);\n return {\n done: true,\n state: new Ct2Sampled(ct2SentUc, sendingCt2),\n epochSecret: null, // Epoch secret already derived in sendCt1\n };\n }\n\n return { done: false, state: this };\n }\n}\n\n// ---------------------------------------------------------------------------\n// State 6: Ct2Sampled\n// ---------------------------------------------------------------------------\n\n/**\n * ct2 payload (ct2 + mac) has been encoded. Sending ct2 chunks.\n * Terminal for this epoch once all chunks sent and next epoch begins.\n */\nexport class Ct2Sampled {\n constructor(\n public readonly uc: unchunkedSendCt.Ct2Sent,\n public readonly sendingCt2: PolyEncoder,\n ) {}\n\n get epoch(): Epoch {\n return this.uc.epoch;\n }\n\n /** Produce the next ct2 chunk. */\n sendCt2Chunk(): [Ct2Sampled, Chunk] {\n const chunk = this.sendingCt2.nextChunk();\n return [this, chunk];\n }\n\n /**\n * Transition to the next epoch's send_ek KeysUnsampled.\n */\n recvNextEpoch(_epoch: Epoch): sendEk.KeysUnsampled {\n const nextEpoch = this.uc.nextEpoch;\n const nextUc = new unchunkedSendEk.KeysUnsampled(nextEpoch, this.uc.auth);\n return new sendEk.KeysUnsampled(nextUc);\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Chunked state machine dispatcher for SPQR V1.\n *\n * Provides the top-level send/recv interface that dispatches to the\n * appropriate chunked send_ek or send_ct state, handling epoch\n * validation and state transitions.\n */\n\nimport type { Chunk } from \"../../encoding/polynomial.js\";\nimport type { Epoch, EpochSecret, RandomBytes } from \"../../types.js\";\nimport { SpqrError, SpqrErrorCode } from \"../../error.js\";\nimport { Authenticator } from \"../../authenticator.js\";\nimport * as unchunked from \"../unchunked/send-ek.js\";\nimport * as sendEk from \"./send-ek.js\";\nimport * as sendCt from \"./send-ct.js\";\n\n// ---------------------------------------------------------------------------\n// Message types\n// ---------------------------------------------------------------------------\n\nexport type MessagePayload =\n | { type: \"none\" }\n | { type: \"hdr\"; chunk: Chunk }\n | { type: \"ek\"; chunk: Chunk }\n | { type: \"ekCt1Ack\"; chunk: Chunk }\n | { type: \"ct1Ack\" }\n | { type: \"ct1\"; chunk: Chunk }\n | { type: \"ct2\"; chunk: Chunk };\n\nexport interface Message {\n epoch: Epoch;\n payload: MessagePayload;\n}\n\nexport interface SendResult {\n msg: Message;\n key: EpochSecret | null;\n state: States;\n}\n\nexport interface RecvResult {\n key: EpochSecret | null;\n state: States;\n}\n\n// ---------------------------------------------------------------------------\n// States discriminated union\n// ---------------------------------------------------------------------------\n\nexport type States =\n | { tag: \"keysUnsampled\"; state: sendEk.KeysUnsampled }\n | { tag: \"keysSampled\"; state: sendEk.KeysSampled }\n | { tag: \"headerSent\"; state: sendEk.HeaderSent }\n | { tag: \"ct1Received\"; state: sendEk.Ct1Received }\n | { tag: \"ekSentCt1Received\"; state: sendEk.EkSentCt1Received }\n | { tag: \"noHeaderReceived\"; state: sendCt.NoHeaderReceived }\n | { tag: \"headerReceived\"; state: sendCt.HeaderReceived }\n | { tag: \"ct1Sampled\"; state: sendCt.Ct1Sampled }\n | { tag: \"ekReceivedCt1Sampled\"; state: sendCt.EkReceivedCt1Sampled }\n | { tag: \"ct1Acknowledged\"; state: sendCt.Ct1Acknowledged }\n | { tag: \"ct2Sampled\"; state: sendCt.Ct2Sampled };\n\n// ---------------------------------------------------------------------------\n// Epoch accessor\n// ---------------------------------------------------------------------------\n\nfunction getEpoch(s: States): Epoch {\n return s.state.epoch;\n}\n\n// ---------------------------------------------------------------------------\n// Initialization\n// ---------------------------------------------------------------------------\n\n/**\n * Initialize Alice (send_ek side) at epoch 1.\n */\nexport function initA(authKey: Uint8Array): States {\n const auth = Authenticator.create(authKey, 1n);\n const ucState = new unchunked.KeysUnsampled(1n, auth);\n return {\n tag: \"keysUnsampled\",\n state: new sendEk.KeysUnsampled(ucState),\n };\n}\n\n/**\n * Initialize Bob (send_ct side) at epoch 1.\n */\nexport function initB(authKey: Uint8Array): States {\n return {\n tag: \"noHeaderReceived\",\n state: sendCt.NoHeaderReceived.create(authKey),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Send\n// ---------------------------------------------------------------------------\n\n/**\n * Produce the next outgoing message from the current state.\n */\nexport function send(current: States, rng: RandomBytes): SendResult {\n const epoch = getEpoch(current);\n\n switch (current.tag) {\n case \"keysUnsampled\": {\n const [next, chunk] = current.state.sendHdrChunk(rng);\n return {\n msg: { epoch, payload: { type: \"hdr\", chunk } },\n key: null,\n state: { tag: \"keysSampled\", state: next },\n };\n }\n\n case \"keysSampled\": {\n const [next, chunk] = current.state.sendHdrChunk();\n return {\n msg: { epoch, payload: { type: \"hdr\", chunk } },\n key: null,\n state: { tag: \"keysSampled\", state: next },\n };\n }\n\n case \"headerSent\": {\n const [next, chunk] = current.state.sendEkChunk();\n return {\n msg: { epoch, payload: { type: \"ek\", chunk } },\n key: null,\n state: { tag: \"headerSent\", state: next },\n };\n }\n\n case \"ct1Received\": {\n const [next, chunk] = current.state.sendEkChunk();\n return {\n msg: { epoch, payload: { type: \"ekCt1Ack\", chunk } },\n key: null,\n state: { tag: \"ct1Received\", state: next },\n };\n }\n\n case \"ekSentCt1Received\": {\n return {\n msg: { epoch, payload: { type: \"ct1Ack\" } },\n key: null,\n state: current,\n };\n }\n\n case \"noHeaderReceived\": {\n return {\n msg: { epoch, payload: { type: \"none\" } },\n key: null,\n state: current,\n };\n }\n\n case \"headerReceived\": {\n const [next, chunk, epochSecret] = current.state.sendCt1Chunk(rng);\n return {\n msg: { epoch, payload: { type: \"ct1\", chunk } },\n key: epochSecret,\n state: { tag: \"ct1Sampled\", state: next },\n };\n }\n\n case \"ct1Sampled\": {\n const [next, chunk] = current.state.sendCt1Chunk();\n return {\n msg: { epoch, payload: { type: \"ct1\", chunk } },\n key: null,\n state: { tag: \"ct1Sampled\", state: next },\n };\n }\n\n case \"ekReceivedCt1Sampled\": {\n const [next, chunk] = current.state.sendCt1Chunk();\n return {\n msg: { epoch, payload: { type: \"ct1\", chunk } },\n key: null,\n state: { tag: \"ekReceivedCt1Sampled\", state: next },\n };\n }\n\n case \"ct1Acknowledged\": {\n return {\n msg: { epoch, payload: { type: \"none\" } },\n key: null,\n state: current,\n };\n }\n\n case \"ct2Sampled\": {\n const [next, chunk] = current.state.sendCt2Chunk();\n return {\n msg: { epoch, payload: { type: \"ct2\", chunk } },\n key: null,\n state: { tag: \"ct2Sampled\", state: next },\n };\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Recv\n// ---------------------------------------------------------------------------\n\n/**\n * Process an incoming message and transition the state.\n */\nexport function recv(current: States, msg: Message): RecvResult {\n const stateEpoch = getEpoch(current);\n\n // Handle epoch mismatch: messages from the past are ignored\n if (msg.epoch < stateEpoch) {\n return { key: null, state: current };\n }\n\n // Messages from the future are an error (except ct2Sampled epoch+1)\n if (msg.epoch > stateEpoch) {\n if (current.tag === \"ct2Sampled\" && msg.epoch === stateEpoch + 1n) {\n // Next epoch -- transition to KeysUnsampled and return immediately.\n // The incoming message payload is NOT processed in the new state\n // (matches Rust: the peer will retransmit via erasure coding).\n const next = current.state.recvNextEpoch(msg.epoch);\n return { key: null, state: { tag: \"keysUnsampled\", state: next } };\n }\n throw new SpqrError(\n `Epoch too far ahead: state=${stateEpoch}, msg=${msg.epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n // msg.epoch === stateEpoch -- process the payload\n const payload = msg.payload;\n\n switch (current.tag) {\n case \"keysUnsampled\": {\n // Waiting to send -- nothing to receive\n return { key: null, state: current };\n }\n\n case \"keysSampled\": {\n if (payload.type === \"ct1\") {\n const next = current.state.recvCt1Chunk(msg.epoch, payload.chunk);\n return { key: null, state: { tag: \"headerSent\", state: next } };\n }\n return { key: null, state: current };\n }\n\n case \"headerSent\": {\n if (payload.type === \"ct1\") {\n const result = current.state.recvCt1Chunk(msg.epoch, payload.chunk);\n if (result.done) {\n return {\n key: null,\n state: { tag: \"ct1Received\", state: result.state },\n };\n }\n return {\n key: null,\n state: { tag: \"headerSent\", state: result.state },\n };\n }\n return { key: null, state: current };\n }\n\n case \"ct1Received\": {\n if (payload.type === \"ct2\") {\n const next = current.state.recvCt2Chunk(msg.epoch, payload.chunk);\n return {\n key: null,\n state: { tag: \"ekSentCt1Received\", state: next },\n };\n }\n return { key: null, state: current };\n }\n\n case \"ekSentCt1Received\": {\n if (payload.type === \"ct2\") {\n const result = current.state.recvCt2Chunk(msg.epoch, payload.chunk);\n if (result.done) {\n return {\n key: result.epochSecret,\n state: { tag: \"noHeaderReceived\", state: result.state },\n };\n }\n return {\n key: null,\n state: { tag: \"ekSentCt1Received\", state: result.state },\n };\n }\n return { key: null, state: current };\n }\n\n case \"noHeaderReceived\": {\n if (payload.type === \"hdr\") {\n const result = current.state.recvHdrChunk(msg.epoch, payload.chunk);\n if (result.done) {\n return {\n key: null,\n state: { tag: \"headerReceived\", state: result.state },\n };\n }\n return {\n key: null,\n state: { tag: \"noHeaderReceived\", state: result.state },\n };\n }\n return { key: null, state: current };\n }\n\n case \"headerReceived\": {\n // Waiting to send ct1 -- nothing to receive in this state\n return { key: null, state: current };\n }\n\n case \"ct1Sampled\": {\n if (payload.type === \"ek\") {\n const result = current.state.recvEkChunk(msg.epoch, payload.chunk, false);\n return mapCt1SampledResult(result);\n }\n if (payload.type === \"ekCt1Ack\") {\n const result = current.state.recvEkChunk(msg.epoch, payload.chunk, true);\n return mapCt1SampledResult(result);\n }\n return { key: null, state: current };\n }\n\n case \"ekReceivedCt1Sampled\": {\n if (payload.type === \"ct1Ack\" || payload.type === \"ekCt1Ack\") {\n const next = current.state.recvCt1Ack(msg.epoch);\n return {\n key: null,\n state: { tag: \"ct2Sampled\", state: next },\n };\n }\n return { key: null, state: current };\n }\n\n case \"ct1Acknowledged\": {\n if (payload.type === \"ek\" || payload.type === \"ekCt1Ack\") {\n const chunk = payload.type === \"ek\" ? payload.chunk : payload.chunk;\n const result = current.state.recvEkChunk(msg.epoch, chunk);\n if (result.done) {\n return {\n key: result.epochSecret,\n state: { tag: \"ct2Sampled\", state: result.state },\n };\n }\n return {\n key: null,\n state: { tag: \"ct1Acknowledged\", state: result.state },\n };\n }\n return { key: null, state: current };\n }\n\n case \"ct2Sampled\": {\n // If we receive a message for the current epoch, nothing to do\n // (next epoch handled above)\n return { key: null, state: current };\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction mapCt1SampledResult(result: sendCt.Ct1SampledRecvChunk): RecvResult {\n switch (result.tag) {\n case \"done\":\n return {\n key: result.epochSecret,\n state: { tag: \"ct2Sampled\", state: result.state },\n };\n case \"stillSending\":\n return {\n key: result.epochSecret,\n state: { tag: \"ekReceivedCt1Sampled\", state: result.state },\n };\n case \"stillReceiving\":\n return {\n key: null,\n state: { tag: \"ct1Acknowledged\", state: result.state },\n };\n case \"stillReceivingStillSending\":\n return {\n key: null,\n state: { tag: \"ct1Sampled\", state: result.state },\n };\n }\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Custom binary V1 message serialization for chunked SPQR.\n *\n * Wire format:\n * [version: u8] 1 byte (V1 = 1)\n * [epoch: varint] 1-10 bytes (LEB128)\n * [index: varint] 1-5 bytes (LEB128)\n * [msg_type: u8] 1 byte (0=None, 1=Hdr, 2=Ek, 3=EkCt1Ack, 4=Ct1Ack, 5=Ct1, 6=Ct2)\n * [chunk_index: varint] + [chunk_data: 32 bytes] (optional, if msg_type has a chunk)\n */\n\nimport type { Chunk } from \"../../encoding/polynomial.js\";\nimport type { Message, MessagePayload } from \"./states.js\";\n\n// ---------------------------------------------------------------------------\n// Message type enum\n// ---------------------------------------------------------------------------\n\nconst enum MessageType {\n None = 0,\n Hdr = 1,\n Ek = 2,\n EkCt1Ack = 3,\n Ct1Ack = 4,\n Ct1 = 5,\n Ct2 = 6,\n}\n\n// ---------------------------------------------------------------------------\n// Varint encoding/decoding (LEB128, matching protobuf varint)\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a bigint as LEB128 varint into the output array.\n */\nexport function encodeVarint(value: bigint, into: number[]): void {\n let v = value;\n if (v < 0n) v = 0n;\n do {\n let byte = Number(v & 0x7fn);\n v >>= 7n;\n if (v > 0n) {\n byte |= 0x80;\n }\n into.push(byte);\n } while (v > 0n);\n}\n\n/**\n * Decode a LEB128 varint from a Uint8Array at the given offset.\n * Updates offset.offset in place.\n */\nexport function decodeVarint(from: Uint8Array, at: { offset: number }): bigint {\n let result = 0n;\n let shift = 0n;\n while (shift < 70n) {\n if (at.offset >= from.length) {\n throw new Error(\"Varint: unexpected end of data\");\n }\n const byte = from[at.offset++];\n result |= BigInt(byte & 0x7f) << shift;\n if ((byte & 0x80) === 0) {\n return result;\n }\n shift += 7n;\n }\n throw new Error(\"Varint: too many bytes\");\n}\n\n/**\n * Encode a number (u32) as LEB128 varint into the output array.\n */\nfunction encodeVarint32(value: number, into: number[]): void {\n let v = value >>> 0;\n do {\n let byte = v & 0x7f;\n v >>>= 7;\n if (v > 0) {\n byte |= 0x80;\n }\n into.push(byte);\n } while (v > 0);\n}\n\n/**\n * Decode a LEB128 varint as a u32 number.\n */\nfunction decodeVarint32(from: Uint8Array, at: { offset: number }): number {\n let result = 0;\n let shift = 0;\n while (shift < 35) {\n if (at.offset >= from.length) {\n throw new Error(\"Varint32: unexpected end of data\");\n }\n const byte = from[at.offset++];\n result |= (byte & 0x7f) << shift;\n if ((byte & 0x80) === 0) {\n return result >>> 0;\n }\n shift += 7;\n }\n throw new Error(\"Varint32: too many bytes\");\n}\n\n// ---------------------------------------------------------------------------\n// Chunk serialization\n// ---------------------------------------------------------------------------\n\nconst CHUNK_DATA_SIZE = 32;\n\n/** Encode a chunk (index varint + 32 data bytes) into the output array. */\nexport function encodeChunk(chunk: Chunk, into: number[]): void {\n encodeVarint32(chunk.index, into);\n for (let i = 0; i < CHUNK_DATA_SIZE; i++) {\n into.push(chunk.data[i]);\n }\n}\n\n/** Decode a chunk from a Uint8Array at the given offset. */\nexport function decodeChunk(from: Uint8Array, at: { offset: number }): Chunk {\n const index = decodeVarint32(from, at);\n if (at.offset + CHUNK_DATA_SIZE > from.length || index > 0xffff) {\n throw new Error(\"Chunk: invalid chunk (data too short or index exceeds u16)\");\n }\n const data = from.slice(at.offset, at.offset + CHUNK_DATA_SIZE);\n at.offset += CHUNK_DATA_SIZE;\n return { index, data };\n}\n\n// ---------------------------------------------------------------------------\n// Message serialization\n// ---------------------------------------------------------------------------\n\n/** Protocol version */\nconst V1 = 1;\n\n/**\n * Serialize a Message with a given sequence index into binary wire format.\n */\nexport function serializeMessage(msg: Message, index: number): Uint8Array {\n const out: number[] = [];\n\n // Version byte\n out.push(V1);\n\n // Epoch (bigint varint)\n encodeVarint(msg.epoch, out);\n\n // Index (u32 varint)\n encodeVarint32(index, out);\n\n // Message type + payload\n const payload = msg.payload;\n switch (payload.type) {\n case \"none\":\n out.push(MessageType.None);\n break;\n case \"hdr\":\n out.push(MessageType.Hdr);\n encodeChunk(payload.chunk, out);\n break;\n case \"ek\":\n out.push(MessageType.Ek);\n encodeChunk(payload.chunk, out);\n break;\n case \"ekCt1Ack\":\n out.push(MessageType.EkCt1Ack);\n encodeChunk(payload.chunk, out);\n break;\n case \"ct1Ack\":\n out.push(MessageType.Ct1Ack);\n // No value byte -- matches Rust wire format (Ct1Ack has no payload)\n break;\n case \"ct1\":\n out.push(MessageType.Ct1);\n encodeChunk(payload.chunk, out);\n break;\n case \"ct2\":\n out.push(MessageType.Ct2);\n encodeChunk(payload.chunk, out);\n break;\n }\n\n return new Uint8Array(out);\n}\n\n/**\n * Deserialize a Message from binary wire format.\n */\nexport function deserializeMessage(from: Uint8Array): {\n msg: Message;\n index: number;\n bytesRead: number;\n} {\n const at = { offset: 0 };\n\n // Version byte\n if (at.offset >= from.length) {\n throw new Error(\"Message: empty data\");\n }\n const version = from[at.offset++];\n if (version !== V1) {\n throw new Error(`Message: unsupported version ${version}`);\n }\n\n // Epoch\n const epoch = decodeVarint(from, at);\n if (epoch === 0n) {\n throw new Error(\"Message: epoch must be > 0\");\n }\n\n // Index\n const index = decodeVarint32(from, at);\n\n // Message type\n if (at.offset >= from.length) {\n throw new Error(\"Message: missing message type\");\n }\n const msgType = from[at.offset++];\n\n let payload: MessagePayload;\n switch (msgType as MessageType) {\n case MessageType.None:\n payload = { type: \"none\" };\n break;\n case MessageType.Hdr:\n payload = { type: \"hdr\", chunk: decodeChunk(from, at) };\n break;\n case MessageType.Ek:\n payload = { type: \"ek\", chunk: decodeChunk(from, at) };\n break;\n case MessageType.EkCt1Ack:\n payload = { type: \"ekCt1Ack\", chunk: decodeChunk(from, at) };\n break;\n case MessageType.Ct1Ack:\n // No value byte -- matches Rust (hardcoded true, no data after type byte)\n payload = { type: \"ct1Ack\" };\n break;\n case MessageType.Ct1:\n payload = { type: \"ct1\", chunk: decodeChunk(from, at) };\n break;\n case MessageType.Ct2:\n payload = { type: \"ct2\", chunk: decodeChunk(from, at) };\n break;\n default:\n throw new Error(`Message: unknown message type ${msgType}`);\n }\n\n return {\n msg: { epoch, payload },\n index,\n bytesRead: at.offset,\n };\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Chunked state machine for SPQR V1.\n *\n * Provides erasure-coded chunk-by-chunk data transfer wrapping the\n * unchunked V1 state machine.\n */\n\n// Wire up the circular dependency factory before any re-exports\nimport { _setCreateSendCtNoHeaderReceived } from \"./send-ek.js\";\nimport { NoHeaderReceived } from \"./send-ct.js\";\nimport type { PolyDecoder } from \"../../encoding/polynomial.js\";\nimport type * as unchunkedSendCt from \"../unchunked/send-ct.js\";\n\n_setCreateSendCtNoHeaderReceived(\n (uc: unchunkedSendCt.NoHeaderReceived, receivingHdr: PolyDecoder) =>\n new NoHeaderReceived(uc, receivingHdr),\n);\n\n// States dispatcher\nexport {\n type States,\n type Message,\n type MessagePayload,\n type SendResult,\n type RecvResult,\n initA,\n initB,\n send,\n recv,\n} from \"./states.js\";\n\n// Message serialization\nexport { serializeMessage, deserializeMessage } from \"./message.js\";\n\n// Chunked send_ek states\nexport {\n KeysUnsampled,\n KeysSampled,\n HeaderSent,\n Ct1Received,\n EkSentCt1Received,\n type HeaderSentRecvChunk,\n type EkSentCt1ReceivedRecvChunk,\n} from \"./send-ek.js\";\n\n// Chunked send_ct states\nexport {\n NoHeaderReceived,\n HeaderReceived,\n Ct1Sampled,\n EkReceivedCt1Sampled,\n Ct1Acknowledged,\n Ct2Sampled,\n type NoHeaderReceivedRecvChunk,\n type Ct1SampledRecvChunk,\n type Ct1AcknowledgedRecvChunk,\n} from \"./send-ct.js\";\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Serialization bridge between runtime States and PbV1State protobuf.\n *\n * Converts the runtime discriminated-union States objects to/from their\n * protobuf representations so that the top-level API can persist state\n * as opaque bytes.\n */\n\nimport type { PbV1State, PbChunkedState } from \"../../proto/pq-ratchet-types.js\";\nimport { Authenticator } from \"../../authenticator.js\";\nimport { PolyEncoder, PolyDecoder } from \"../../encoding/polynomial.js\";\n\n// Unchunked state classes\nimport * as ucSendEk from \"../unchunked/send-ek.js\";\nimport * as ucSendCt from \"../unchunked/send-ct.js\";\n\n// Chunked state classes\nimport * as sendEk from \"./send-ek.js\";\nimport * as sendCt from \"./send-ct.js\";\n\nimport type { States } from \"./states.js\";\nimport type { Epoch } from \"../../types.js\";\n\n// ---------------------------------------------------------------------------\n// States -> PbV1State\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize a runtime States object into PbV1State for protobuf encoding.\n * Stores the epoch as field 12 so it can be recovered on deserialization.\n */\nexport function statesToPb(s: States): PbV1State {\n const epoch = s.state.epoch;\n return { innerState: chunkedStateToPb(s), epoch };\n}\n\nfunction chunkedStateToPb(s: States): PbChunkedState {\n switch (s.tag) {\n case \"keysUnsampled\": {\n const st = s.state;\n return {\n type: \"keysUnsampled\",\n uc: { auth: st.uc.auth.toProto() },\n };\n }\n case \"keysSampled\": {\n const st = s.state;\n return {\n type: \"keysSampled\",\n uc: {\n auth: st.uc.auth.toProto(),\n ek: Uint8Array.from(st.uc.ek),\n dk: Uint8Array.from(st.uc.dk),\n hdr: new Uint8Array(0),\n hdrMac: new Uint8Array(0),\n },\n sendingHdr: st.sendingHdr.toProto(),\n };\n }\n case \"headerSent\": {\n const st = s.state;\n return {\n type: \"headerSent\",\n uc: {\n auth: st.uc.auth.toProto(),\n ek: new Uint8Array(0),\n dk: Uint8Array.from(st.uc.dk),\n },\n sendingEk: st.sendingEk.toProto(),\n receivingCt1: st.receivingCt1.toProto(),\n };\n }\n case \"ct1Received\": {\n const st = s.state;\n return {\n type: \"ct1Received\",\n uc: {\n auth: st.uc.auth.toProto(),\n dk: Uint8Array.from(st.uc.dk),\n ct1: Uint8Array.from(st.uc.ct1),\n },\n sendingEk: st.sendingEk.toProto(),\n };\n }\n case \"ekSentCt1Received\": {\n const st = s.state;\n return {\n type: \"ekSentCt1Received\",\n uc: {\n auth: st.uc.auth.toProto(),\n dk: Uint8Array.from(st.uc.dk),\n ct1: Uint8Array.from(st.uc.ct1),\n },\n receivingCt2: st.receivingCt2.toProto(),\n };\n }\n case \"noHeaderReceived\": {\n const st = s.state;\n return {\n type: \"noHeaderReceived\",\n uc: { auth: st.uc.auth.toProto() },\n receivingHdr: st.receivingHdr.toProto(),\n };\n }\n case \"headerReceived\": {\n const st = s.state;\n return {\n type: \"headerReceived\",\n uc: {\n auth: st.uc.auth.toProto(),\n hdr: Uint8Array.from(st.uc.hdr),\n es: new Uint8Array(0),\n ct1: new Uint8Array(0),\n ss: new Uint8Array(0),\n },\n receivingEk: st.receivingEk.toProto(),\n };\n }\n case \"ct1Sampled\": {\n const st = s.state;\n return {\n type: \"ct1Sampled\",\n uc: {\n auth: st.uc.auth.toProto(),\n hdr: Uint8Array.from(st.uc.hdr),\n es: Uint8Array.from(st.uc.es),\n ct1: Uint8Array.from(st.uc.ct1),\n },\n sendingCt1: st.sendingCt1.toProto(),\n receivingEk: st.receivingEk.toProto(),\n };\n }\n case \"ekReceivedCt1Sampled\": {\n const st = s.state;\n return {\n type: \"ekReceivedCt1Sampled\",\n uc: {\n auth: st.uc.auth.toProto(),\n hdr: new Uint8Array(0),\n es: Uint8Array.from(st.uc.es),\n ek: Uint8Array.from(st.uc.ek),\n ct1: Uint8Array.from(st.uc.ct1),\n },\n sendingCt1: st.sendingCt1.toProto(),\n };\n }\n case \"ct1Acknowledged\": {\n const st = s.state;\n return {\n type: \"ct1Acknowledged\",\n uc: {\n auth: st.uc.auth.toProto(),\n hdr: Uint8Array.from(st.uc.hdr),\n es: Uint8Array.from(st.uc.es),\n ct1: Uint8Array.from(st.uc.ct1),\n },\n receivingEk: st.receivingEk.toProto(),\n };\n }\n case \"ct2Sampled\": {\n const st = s.state;\n return {\n type: \"ct2Sampled\",\n uc: { auth: st.uc.auth.toProto() },\n sendingCt2: st.sendingCt2.toProto(),\n };\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// PbV1State -> States\n// ---------------------------------------------------------------------------\n\n/**\n * Deserialize a PbV1State back into a runtime States object.\n *\n * @param pb - The protobuf V1 state\n * @returns The reconstructed runtime States\n */\nexport function statesFromPb(pb: PbV1State): States {\n if (pb.innerState === undefined) {\n throw new Error(\"PbV1State has no innerState\");\n }\n const epoch = pb.epoch ?? 1n;\n return chunkedStateFromPb(pb.innerState, epoch);\n}\n\nfunction chunkedStateFromPb(cs: PbChunkedState, epoch: Epoch): States {\n switch (cs.type) {\n case \"keysUnsampled\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendEk.KeysUnsampled(epoch, auth);\n return { tag: \"keysUnsampled\", state: new sendEk.KeysUnsampled(ucState) };\n }\n case \"keysSampled\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendEk.HeaderSent(epoch, auth, cs.uc.ek, cs.uc.dk);\n const encoder = PolyEncoder.fromProto(cs.sendingHdr);\n return { tag: \"keysSampled\", state: new sendEk.KeysSampled(ucState, encoder) };\n }\n case \"headerSent\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendEk.EkSent(epoch, auth, cs.uc.dk);\n const encoder = PolyEncoder.fromProto(cs.sendingEk);\n const decoder = PolyDecoder.fromProto(cs.receivingCt1);\n return { tag: \"headerSent\", state: new sendEk.HeaderSent(ucState, encoder, decoder) };\n }\n case \"ct1Received\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendEk.EkSentCt1Received(epoch, auth, cs.uc.dk, cs.uc.ct1);\n const encoder = PolyEncoder.fromProto(cs.sendingEk);\n return { tag: \"ct1Received\", state: new sendEk.Ct1Received(ucState, encoder) };\n }\n case \"ekSentCt1Received\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendEk.EkSentCt1Received(epoch, auth, cs.uc.dk, cs.uc.ct1);\n const decoder = PolyDecoder.fromProto(cs.receivingCt2);\n return { tag: \"ekSentCt1Received\", state: new sendEk.EkSentCt1Received(ucState, decoder) };\n }\n case \"noHeaderReceived\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendCt.NoHeaderReceived(epoch, auth);\n const decoder = PolyDecoder.fromProto(cs.receivingHdr);\n return { tag: \"noHeaderReceived\", state: new sendCt.NoHeaderReceived(ucState, decoder) };\n }\n case \"headerReceived\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendCt.HeaderReceived(epoch, auth, cs.uc.hdr);\n const decoder = PolyDecoder.fromProto(cs.receivingEk);\n return { tag: \"headerReceived\", state: new sendCt.HeaderReceived(ucState, decoder) };\n }\n case \"ct1Sampled\": {\n const auth = authFromPb(cs.uc.auth);\n // Ct1Sent stores (epoch, auth, hdr, es, ct1) -- ct1 needed for MAC in sendCt2\n const ucState = new ucSendCt.Ct1Sent(epoch, auth, cs.uc.hdr, cs.uc.es, cs.uc.ct1);\n const encoder = PolyEncoder.fromProto(cs.sendingCt1);\n const decoder = PolyDecoder.fromProto(cs.receivingEk);\n return { tag: \"ct1Sampled\", state: new sendCt.Ct1Sampled(ucState, encoder, decoder) };\n }\n case \"ekReceivedCt1Sampled\": {\n const auth = authFromPb(cs.uc.auth);\n // Ct1SentEkReceived stores (epoch, auth, es, ek, ct1) -- ct1 needed for MAC in sendCt2\n const ucState = new ucSendCt.Ct1SentEkReceived(epoch, auth, cs.uc.es, cs.uc.ek, cs.uc.ct1);\n const encoder = PolyEncoder.fromProto(cs.sendingCt1);\n return {\n tag: \"ekReceivedCt1Sampled\",\n state: new sendCt.EkReceivedCt1Sampled(ucState, encoder),\n };\n }\n case \"ct1Acknowledged\": {\n const auth = authFromPb(cs.uc.auth);\n // Ct1Sent stores (epoch, auth, hdr, es, ct1) -- ct1 needed for MAC in sendCt2\n const ucState = new ucSendCt.Ct1Sent(epoch, auth, cs.uc.hdr, cs.uc.es, cs.uc.ct1);\n const decoder = PolyDecoder.fromProto(cs.receivingEk);\n return { tag: \"ct1Acknowledged\", state: new sendCt.Ct1Acknowledged(ucState, decoder) };\n }\n case \"ct2Sampled\": {\n const auth = authFromPb(cs.uc.auth);\n const ucState = new ucSendCt.Ct2Sent(epoch, auth);\n const encoder = PolyEncoder.fromProto(cs.sendingCt2);\n return { tag: \"ct2Sampled\", state: new sendCt.Ct2Sampled(ucState, encoder) };\n }\n }\n}\n\nfunction authFromPb(pb: { rootKey: Uint8Array; macKey: Uint8Array } | undefined): Authenticator {\n if (pb === undefined) {\n return Authenticator.fromProto({\n rootKey: new Uint8Array(32),\n macKey: new Uint8Array(32),\n });\n }\n return Authenticator.fromProto(pb);\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Shared types for the SPQR protocol.\n */\n\n/** Epoch identifier (u64 in Rust, bigint in TypeScript) */\nexport type Epoch = bigint;\n\n/** Secret key material (32 bytes) */\nexport type Secret = Uint8Array;\n\n/** Message key output from send/recv */\nexport type MessageKey = Uint8Array | null;\n\n/** Opaque serialized state (protobuf bytes) */\nexport type SerializedState = Uint8Array;\n\n/** Opaque serialized message (protobuf V1Msg bytes) */\nexport type SerializedMessage = Uint8Array;\n\n/** Interface for random byte generation */\nexport type RandomBytes = (length: number) => Uint8Array;\n\n/** Result of send() */\nexport interface Send {\n state: SerializedState;\n msg: SerializedMessage;\n key: Secret | null;\n}\n\n/** Result of recv() */\nexport interface Recv {\n state: SerializedState;\n key: Secret | null;\n}\n\n/** Epoch secret output from state machine */\nexport interface EpochSecret {\n epoch: Epoch;\n secret: Secret;\n}\n\n/** Parameters for initializing SPQR */\nexport interface Params {\n direction: Direction;\n version: Version;\n minVersion: Version;\n authKey: Uint8Array;\n chainParams: ChainParams;\n}\n\n/** Chain configuration parameters */\nexport interface ChainParams {\n maxJump: number;\n maxOooKeys: number;\n}\n\n/** Protocol version */\nexport enum Version {\n V0 = 0,\n V1 = 1,\n}\n\n/** Communication direction */\nexport enum Direction {\n A2B = 0,\n B2A = 1,\n}\n\n/** Current version negotiation status */\nexport type CurrentVersion =\n | { type: \"still_negotiating\"; version: Version; minVersion: Version }\n | { type: \"negotiation_complete\"; version: Version };\n\n/** Internal secret output from state transitions */\nexport type SecretOutput =\n | { type: \"none\" }\n | { type: \"send\"; secret: Secret }\n | { type: \"recv\"; secret: Secret };\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * SPQR Symmetric Chain -- epoch-based key derivation with forward/backward secrecy.\n *\n * Ported from Signal's spqr crate: chain.rs\n *\n * The Chain manages send/receive keys across epochs. Each epoch has two\n * directional chains (A2B and B2A). Keys are derived using HKDF-SHA256\n * with specific info strings that MUST match the Rust implementation\n * exactly (including the double space in \"Chain Start\").\n */\n\nimport { hkdfSha256 } from \"./kdf.js\";\nimport { concat, uint32ToBE4 } from \"./util.js\";\nimport {\n ZERO_SALT,\n LABEL_CHAIN_START,\n LABEL_CHAIN_NEXT,\n LABEL_CHAIN_ADD_EPOCH,\n DEFAULT_MAX_JUMP,\n DEFAULT_MAX_OOO_KEYS,\n EPOCHS_TO_KEEP_PRIOR_TO_SEND_EPOCH,\n KEY_ENTRY_SIZE,\n} from \"./constants.js\";\nimport { SpqrError, SpqrErrorCode } from \"./error.js\";\nimport type { Epoch, EpochSecret, ChainParams } from \"./types.js\";\nimport { Direction } from \"./types.js\";\nimport type {\n PbChain,\n PbChainParams,\n PbEpoch,\n PbEpochDirection,\n} from \"./proto/pq-ratchet-types.js\";\n\n// Re-export Direction from types\nexport { Direction } from \"./types.js\";\n\n// ---- Pre-encoded info labels ----\nconst enc = new TextEncoder();\nconst CHAIN_START_INFO = enc.encode(LABEL_CHAIN_START);\nconst CHAIN_NEXT_INFO = enc.encode(LABEL_CHAIN_NEXT);\nconst CHAIN_ADD_EPOCH_INFO = enc.encode(LABEL_CHAIN_ADD_EPOCH);\n\n// ---- Helper functions ----\n\nfunction resolveMaxJump(params: ChainParams): number {\n return params.maxJump > 0 ? params.maxJump : DEFAULT_MAX_JUMP;\n}\n\nfunction resolveMaxOooKeys(params: ChainParams): number {\n return params.maxOooKeys > 0 ? params.maxOooKeys : DEFAULT_MAX_OOO_KEYS;\n}\n\nfunction trimSize(params: ChainParams): number {\n const maxOoo = resolveMaxOooKeys(params);\n return Math.floor((maxOoo * 11) / 10) + 1;\n}\n\nfunction switchDirection(d: Direction): Direction {\n // Direction.A2B = 0, Direction.B2A = 1\n return d === Direction.A2B ? Direction.B2A : Direction.A2B;\n}\n\n// ---- KeyHistory ----\n\n/**\n * Stores out-of-order keys as packed [index_be32 (4 bytes)][key (32 bytes)] entries.\n * Matches Rust KeyHistory data layout exactly.\n */\nclass KeyHistory {\n data: Uint8Array;\n private length: number;\n\n constructor(data?: Uint8Array) {\n this.data = data !== undefined ? Uint8Array.from(data) : new Uint8Array(0);\n this.length = this.data.length;\n }\n\n add(index: number, key: Uint8Array, _params: ChainParams): void {\n const entry = new Uint8Array(KEY_ENTRY_SIZE);\n const view = new DataView(entry.buffer);\n view.setUint32(0, index, false); // big-endian\n entry.set(key, 4);\n\n const newData = new Uint8Array(this.length + KEY_ENTRY_SIZE);\n newData.set(this.data.subarray(0, this.length));\n newData.set(entry, this.length);\n this.data = newData;\n this.length += KEY_ENTRY_SIZE;\n }\n\n gc(currentKey: number, params: ChainParams): void {\n const maxOoo = resolveMaxOooKeys(params);\n if (this.length >= trimSize(params) * KEY_ENTRY_SIZE) {\n if (currentKey < maxOoo) {\n throw new Error(\"KeyHistory.gc: currentKey < maxOooKeys (corrupted state)\");\n }\n const trimHorizon = currentKey - maxOoo;\n\n let i = 0;\n while (i < this.length) {\n const view = new DataView(this.data.buffer, this.data.byteOffset + i, 4);\n const idx = view.getUint32(0, false);\n if (trimHorizon > idx) {\n this.removeAt(i);\n // Don't advance i -- replacement might also be old\n } else {\n i += KEY_ENTRY_SIZE;\n }\n }\n }\n }\n\n clear(): void {\n this.data = new Uint8Array(0);\n this.length = 0;\n }\n\n get(at: number, currentCtr: number, params: ChainParams): Uint8Array {\n const maxOoo = resolveMaxOooKeys(params);\n if (at + maxOoo < currentCtr) {\n throw new SpqrError(`Key trimmed: ${at}`, SpqrErrorCode.KeyTrimmed);\n }\n\n const want = new Uint8Array(4);\n new DataView(want.buffer).setUint32(0, at, false);\n\n for (let i = 0; i < this.length; i += KEY_ENTRY_SIZE) {\n if (\n this.data[i] === want[0] &&\n this.data[i + 1] === want[1] &&\n this.data[i + 2] === want[2] &&\n this.data[i + 3] === want[3]\n ) {\n const key = this.data.slice(i + 4, i + KEY_ENTRY_SIZE);\n this.removeAt(i);\n return key;\n }\n }\n\n throw new SpqrError(`Key already requested: ${at}`, SpqrErrorCode.KeyAlreadyRequested);\n }\n\n private removeAt(index: number): void {\n if (index + KEY_ENTRY_SIZE < this.length) {\n // Swap-remove: move last entry to this position\n const lastStart = this.length - KEY_ENTRY_SIZE;\n this.data.copyWithin(index, lastStart, this.length);\n }\n this.length -= KEY_ENTRY_SIZE;\n }\n\n /** Serialize to raw bytes for protobuf storage */\n serialize(): Uint8Array {\n return this.data.slice(0, this.length);\n }\n}\n\n// ---- ChainEpochDirection ----\n\n/**\n * One directional chain within an epoch (send or recv).\n * Manages a ratcheting key derivation with HKDF.\n */\nclass ChainEpochDirection {\n ctr: number;\n next: Uint8Array;\n prev: KeyHistory;\n\n constructor(key: Uint8Array, ctr?: number, prev?: Uint8Array) {\n this.ctr = ctr ?? 0;\n this.next = Uint8Array.from(key);\n this.prev = new KeyHistory(prev);\n }\n\n /**\n * Derive the next key in the chain.\n * Returns [index, key].\n */\n nextKey(): [number, Uint8Array] {\n this.ctr += 1;\n\n const ctrBe = uint32ToBE4(this.ctr);\n const info = concat(ctrBe, CHAIN_NEXT_INFO);\n\n const gen = hkdfSha256(this.next, ZERO_SALT, info, 64);\n this.next = gen.slice(0, 32);\n const key = gen.slice(32, 64);\n\n return [this.ctr, key];\n }\n\n /**\n * Internal: derive next key without consuming it publicly.\n * Used for skipping ahead to build out-of-order key history.\n */\n private static nextKeyInternal(\n next: Uint8Array,\n ctr: number,\n ): { next: Uint8Array; ctr: number; index: number; key: Uint8Array } {\n ctr += 1;\n\n const ctrBe = uint32ToBE4(ctr);\n const info = concat(ctrBe, CHAIN_NEXT_INFO);\n\n const gen = hkdfSha256(next, ZERO_SALT, info, 64);\n\n return {\n next: gen.slice(0, 32),\n ctr,\n index: ctr,\n key: gen.slice(32, 64),\n };\n }\n\n /**\n * Get the key at a specific counter position.\n * Supports out-of-order access via KeyHistory.\n */\n key(at: number, params: ChainParams): Uint8Array {\n const maxJump = resolveMaxJump(params);\n const maxOoo = resolveMaxOooKeys(params);\n\n if (at > this.ctr) {\n if (at - this.ctr > maxJump) {\n throw new SpqrError(`Key jump: ${this.ctr} - ${at}`, SpqrErrorCode.KeyJump);\n }\n } else if (at < this.ctr) {\n return this.prev.get(at, this.ctr, params);\n } else {\n // at === this.ctr: already returned\n throw new SpqrError(`Key already requested: ${at}`, SpqrErrorCode.KeyAlreadyRequested);\n }\n\n if (at > this.ctr + maxOoo) {\n // About to make all currently-held keys obsolete\n this.prev.clear();\n }\n\n while (at > this.ctr + 1) {\n const result = ChainEpochDirection.nextKeyInternal(this.next, this.ctr);\n this.next = result.next;\n this.ctr = result.ctr;\n // Only add keys into history if we're not going to immediately GC them\n if (this.ctr + maxOoo >= at) {\n this.prev.add(result.index, result.key, params);\n }\n }\n\n // GC after potentially adding new keys\n this.prev.gc(this.ctr, params);\n\n // Get the requested key\n const result = ChainEpochDirection.nextKeyInternal(this.next, this.ctr);\n this.next = result.next;\n this.ctr = result.ctr;\n return result.key;\n }\n\n clearNext(): void {\n this.next = new Uint8Array(0);\n }\n\n /** Serialize to protobuf EpochDirection */\n toProto(): PbEpochDirection {\n return {\n ctr: this.ctr,\n next: Uint8Array.from(this.next),\n prev: this.prev.serialize(),\n };\n }\n\n static fromProto(pb: PbEpochDirection): ChainEpochDirection {\n return new ChainEpochDirection(pb.next, pb.ctr, pb.prev);\n }\n}\n\n// ---- ChainEpoch ----\n\ninterface ChainEpoch {\n send: ChainEpochDirection;\n recv: ChainEpochDirection;\n}\n\n// ---- Chain ----\n\n/**\n * The main Chain manages send/receive keys across all epochs.\n *\n * Port of Rust's Chain struct from chain.rs.\n * Uses bigint for epoch values (matching Rust u64).\n */\nexport class Chain {\n private readonly dir: Direction;\n private currentEpoch: Epoch;\n private sendEpoch: Epoch;\n private readonly links: ChainEpoch[];\n private nextRoot: Uint8Array;\n private readonly params: ChainParams;\n\n private constructor(\n dir: Direction,\n currentEpoch: Epoch,\n sendEpoch: Epoch,\n links: ChainEpoch[],\n nextRoot: Uint8Array,\n params: ChainParams,\n ) {\n this.dir = dir;\n this.currentEpoch = currentEpoch;\n this.sendEpoch = sendEpoch;\n this.links = links;\n this.nextRoot = nextRoot;\n this.params = params;\n }\n\n /**\n * Create a new chain from an initial key and direction.\n * HKDF info: \"Signal PQ Ratchet V1 Chain Start\" (TWO spaces before Start!)\n *\n * The 96-byte HKDF output is split as:\n * [0..32]: nextRoot\n * [32..64]: A2B chain seed\n * [64..96]: B2A chain seed\n *\n * Direction determines which half is send vs recv.\n */\n static create(\n initialKey: Uint8Array,\n dir: Direction,\n params: ChainParams = { maxJump: DEFAULT_MAX_JUMP, maxOooKeys: DEFAULT_MAX_OOO_KEYS },\n ): Chain {\n const gen = hkdfSha256(initialKey, ZERO_SALT, CHAIN_START_INFO, 96);\n\n const switchedDir = switchDirection(dir);\n\n const sendKey = cedForDirection(gen, dir);\n const recvKey = cedForDirection(gen, switchedDir);\n\n return new Chain(\n dir,\n 0n,\n 0n,\n [\n {\n send: new ChainEpochDirection(sendKey),\n recv: new ChainEpochDirection(recvKey),\n },\n ],\n gen.slice(0, 32),\n params,\n );\n }\n\n /**\n * Add a new epoch to the chain with a shared secret.\n * HKDF info: \"Signal PQ Ratchet V1 Chain Add Epoch\"\n *\n * Salt = current nextRoot, IKM = epochSecret.secret\n */\n addEpoch(epochSecret: EpochSecret): void {\n if (epochSecret.epoch !== this.currentEpoch + 1n) {\n throw new SpqrError(\n `Expected epoch ${this.currentEpoch + 1n}, got ${epochSecret.epoch}`,\n SpqrErrorCode.EpochOutOfRange,\n );\n }\n\n const gen = hkdfSha256(epochSecret.secret, this.nextRoot, CHAIN_ADD_EPOCH_INFO, 96);\n\n this.currentEpoch = epochSecret.epoch;\n this.nextRoot = gen.slice(0, 32);\n\n const sendKey = cedForDirection(gen, this.dir);\n const recvKey = cedForDirection(gen, switchDirection(this.dir));\n\n this.links.push({\n send: new ChainEpochDirection(sendKey),\n recv: new ChainEpochDirection(recvKey),\n });\n }\n\n private epochIdx(epoch: Epoch): number {\n if (epoch > this.currentEpoch) {\n throw new SpqrError(`Epoch not in valid range: ${epoch}`, SpqrErrorCode.EpochOutOfRange);\n }\n const back = Number(this.currentEpoch - epoch);\n if (back >= this.links.length) {\n throw new SpqrError(`Epoch not in valid range: ${epoch}`, SpqrErrorCode.EpochOutOfRange);\n }\n return this.links.length - 1 - back;\n }\n\n /**\n * Get the next send key for a given epoch.\n * Returns [index, key].\n */\n sendKey(epoch: Epoch): [number, Uint8Array] {\n if (epoch < this.sendEpoch) {\n throw new SpqrError(\n `Send key epoch decreased (${this.sendEpoch} -> ${epoch})`,\n SpqrErrorCode.SendKeyEpochDecreased,\n );\n }\n\n let epochIndex = this.epochIdx(epoch);\n\n if (this.sendEpoch !== epoch) {\n this.sendEpoch = epoch;\n\n while (epochIndex > EPOCHS_TO_KEEP_PRIOR_TO_SEND_EPOCH) {\n this.links.shift();\n epochIndex -= 1;\n }\n\n for (let i = 0; i < epochIndex; i++) {\n this.links[i].send.clearNext();\n }\n }\n\n return this.links[epochIndex].send.nextKey();\n }\n\n /**\n * Get a receive key for a given epoch and counter index.\n */\n recvKey(epoch: Epoch, index: number): Uint8Array {\n const epochIndex = this.epochIdx(epoch);\n return this.links[epochIndex].recv.key(index, this.params);\n }\n\n // ---- Protobuf serialization ----\n\n /**\n * Serialize the chain to its protobuf representation.\n * Matches Rust Chain::into_pb().\n */\n toProto(): PbChain {\n return {\n direction: this.dir,\n currentEpoch: this.currentEpoch,\n sendEpoch: this.sendEpoch,\n nextRoot: Uint8Array.from(this.nextRoot),\n links: this.links.map(\n (link): PbEpoch => ({\n send: link.send.toProto(),\n recv: link.recv.toProto(),\n }),\n ),\n params: chainParamsToProto(this.params),\n };\n }\n\n /**\n * Deserialize a chain from its protobuf representation.\n * Matches Rust Chain::from_pb().\n */\n static fromProto(pb: PbChain): Chain {\n const links = pb.links.map(\n (link): ChainEpoch => ({\n send: ChainEpochDirection.fromProto(\n link.send ?? { ctr: 0, next: new Uint8Array(0), prev: new Uint8Array(0) },\n ),\n recv: ChainEpochDirection.fromProto(\n link.recv ?? { ctr: 0, next: new Uint8Array(0), prev: new Uint8Array(0) },\n ),\n }),\n );\n\n const params = chainParamsFromProto(pb.params);\n\n return new Chain(\n pb.direction as Direction,\n pb.currentEpoch,\n pb.sendEpoch,\n links,\n Uint8Array.from(pb.nextRoot),\n params,\n );\n }\n}\n\n// ---- Direction helpers ----\n\n/**\n * Select the chain key for a given direction from a 96-byte HKDF output.\n * A2B uses bytes [32..64], B2A uses bytes [64..96].\n */\nfunction cedForDirection(gen: Uint8Array, dir: Direction): Uint8Array {\n // Direction.A2B = 0 -> [32..64]\n // Direction.B2A = 1 -> [64..96]\n return dir === Direction.A2B ? gen.slice(32, 64) : gen.slice(64, 96);\n}\n\n// ---- ChainParams proto helpers ----\n\n/**\n * Convert ChainParams to protobuf format.\n * Default values are stored as 0 (proto3 convention).\n */\nfunction chainParamsToProto(params: ChainParams): PbChainParams {\n return {\n maxJump: params.maxJump === DEFAULT_MAX_JUMP ? 0 : params.maxJump,\n maxOooKeys: params.maxOooKeys === DEFAULT_MAX_OOO_KEYS ? 0 : params.maxOooKeys,\n };\n}\n\n/**\n * Convert protobuf ChainParams to runtime ChainParams.\n * Zero values are interpreted as defaults.\n */\nfunction chainParamsFromProto(pb?: PbChainParams): ChainParams {\n if (pb === undefined) {\n return { maxJump: DEFAULT_MAX_JUMP, maxOooKeys: DEFAULT_MAX_OOO_KEYS };\n }\n return {\n maxJump: pb.maxJump > 0 ? pb.maxJump : DEFAULT_MAX_JUMP,\n maxOooKeys: pb.maxOooKeys > 0 ? pb.maxOooKeys : DEFAULT_MAX_OOO_KEYS,\n };\n}\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Minimal protobuf encoder/decoder for SPQR wire format.\n * Supports varint (wire type 0) and length-delimited (wire type 2).\n */\n\nimport type {\n PbAuthenticator,\n PbChain,\n PbChainParams,\n PbChunkedState,\n PbChunk,\n PbEpoch,\n PbEpochDirection,\n PbPolynomialDecoder,\n PbPolynomialEncoder,\n PbPqRatchetState,\n PbV1Msg,\n PbV1MsgInner,\n PbV1State,\n PbVersionNegotiation,\n} from \"./pq-ratchet-types.js\";\n\n// ---- Wire types ----\n\nconst WIRE_VARINT = 0;\nconst WIRE_LENGTH_DELIMITED = 2;\n\n// ---- Empty defaults for bytes fields ----\n\nconst EMPTY_BYTES = new Uint8Array(0);\n\n// =========================================================================\n// ProtoWriter\n// =========================================================================\n\nexport class ProtoWriter {\n private readonly parts: Uint8Array[] = [];\n\n writeVarint(fieldNumber: number, value: number | bigint): void {\n if (typeof value === \"bigint\") {\n if (value === 0n) return; // default value, omit\n this.writeTag(fieldNumber, WIRE_VARINT);\n this.writeRawVarint64(value);\n } else {\n if (value === 0) return; // default value, omit\n this.writeTag(fieldNumber, WIRE_VARINT);\n this.writeRawVarint(value);\n }\n }\n\n /** Write a varint field even when the value is zero (for required fields). */\n writeVarintAlways(fieldNumber: number, value: number | bigint): void {\n if (typeof value === \"bigint\") {\n this.writeTag(fieldNumber, WIRE_VARINT);\n this.writeRawVarint64(value);\n } else {\n this.writeTag(fieldNumber, WIRE_VARINT);\n this.writeRawVarint(value);\n }\n }\n\n writeBool(fieldNumber: number, value: boolean): void {\n if (!value) return; // default false, omit\n this.writeTag(fieldNumber, WIRE_VARINT);\n this.writeRawVarint(1);\n }\n\n writeBytes(fieldNumber: number, data: Uint8Array): void {\n if (data.length === 0) return; // default empty, omit\n this.writeTag(fieldNumber, WIRE_LENGTH_DELIMITED);\n this.writeRawVarint(data.length);\n this.parts.push(new Uint8Array(data));\n }\n\n writeMessage(fieldNumber: number, writer: ProtoWriter): void {\n const data = writer.finish();\n if (data.length === 0) return;\n this.writeTag(fieldNumber, WIRE_LENGTH_DELIMITED);\n this.writeRawVarint(data.length);\n this.parts.push(data);\n }\n\n /** For oneof fields, write even if the sub-message is empty. */\n writeMessageAlways(fieldNumber: number, writer: ProtoWriter): void {\n const data = writer.finish();\n this.writeTag(fieldNumber, WIRE_LENGTH_DELIMITED);\n this.writeRawVarint(data.length);\n if (data.length > 0) this.parts.push(data);\n }\n\n writeEnum(fieldNumber: number, value: number): void {\n this.writeVarint(fieldNumber, value);\n }\n\n finish(): Uint8Array {\n let total = 0;\n for (const p of this.parts) total += p.length;\n const result = new Uint8Array(total);\n let offset = 0;\n for (const p of this.parts) {\n result.set(p, offset);\n offset += p.length;\n }\n return result;\n }\n\n private writeTag(fieldNumber: number, wireType: number): void {\n this.writeRawVarint((fieldNumber << 3) | wireType);\n }\n\n private writeRawVarint(value: number): void {\n const buf: number[] = [];\n let v = value >>> 0; // ensure unsigned\n while (v > 0x7f) {\n buf.push((v & 0x7f) | 0x80);\n v >>>= 7;\n }\n buf.push(v & 0x7f);\n this.parts.push(new Uint8Array(buf));\n }\n\n private writeRawVarint64(value: bigint): void {\n const buf: number[] = [];\n let v = value;\n while (v > 0x7fn) {\n buf.push(Number(v & 0x7fn) | 0x80);\n v >>= 7n;\n }\n buf.push(Number(v & 0x7fn));\n this.parts.push(new Uint8Array(buf));\n }\n}\n\n// =========================================================================\n// ProtoReader\n// =========================================================================\n\nexport class ProtoReader {\n private readonly data: Uint8Array;\n private pos: number;\n\n constructor(data: Uint8Array) {\n this.data = data;\n this.pos = 0;\n }\n\n get remaining(): number {\n return this.data.length - this.pos;\n }\n\n get done(): boolean {\n return this.pos >= this.data.length;\n }\n\n readField(): { fieldNumber: number; wireType: number } | null {\n if (this.pos >= this.data.length) return null;\n const tag = this.readRawVarint();\n return { fieldNumber: tag >>> 3, wireType: tag & 0x7 };\n }\n\n readVarint(): number {\n return this.readRawVarint();\n }\n\n readVarint64(): bigint {\n return this.readRawVarint64();\n }\n\n readBool(): boolean {\n return this.readRawVarint() !== 0;\n }\n\n readBytes(): Uint8Array {\n const len = this.readRawVarint();\n const data = this.data.slice(this.pos, this.pos + len);\n this.pos += len;\n return data;\n }\n\n readMessage(): ProtoReader {\n const data = this.readBytes();\n return new ProtoReader(data);\n }\n\n readEnum(): number {\n return this.readRawVarint();\n }\n\n skip(wireType: number): void {\n switch (wireType) {\n case 0: // varint\n this.readRawVarint();\n break;\n case 1: // 64-bit\n this.pos += 8;\n break;\n case 2: {\n // length-delimited\n const len = this.readRawVarint();\n this.pos += len;\n break;\n }\n case 5: // 32-bit\n this.pos += 4;\n break;\n default:\n throw new Error(`Unknown wire type: ${wireType}`);\n }\n }\n\n private readRawVarint(): number {\n let result = 0;\n let shift = 0;\n while (shift < 35) {\n const b = this.data[this.pos++];\n result |= (b & 0x7f) << shift;\n if ((b & 0x80) === 0) return result >>> 0;\n shift += 7;\n }\n throw new Error(\"Varint too long\");\n }\n\n private readRawVarint64(): bigint {\n let result = 0n;\n let shift = 0n;\n while (shift < 70n) {\n const b = this.data[this.pos++];\n result |= BigInt(b & 0x7f) << shift;\n if ((b & 0x80) === 0) return result;\n shift += 7n;\n }\n throw new Error(\"Varint64 too long\");\n }\n}\n\n// =========================================================================\n// ChainParams\n// =========================================================================\n\nexport function encodeChainParams(msg: PbChainParams): Uint8Array {\n const w = new ProtoWriter();\n w.writeVarint(1, msg.maxJump);\n w.writeVarint(2, msg.maxOooKeys);\n return w.finish();\n}\n\nexport function decodeChainParams(data: Uint8Array): PbChainParams {\n const r = new ProtoReader(data);\n let maxJump = 0;\n let maxOooKeys = 0;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n maxJump = r.readVarint();\n break;\n case 2:\n maxOooKeys = r.readVarint();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { maxJump, maxOooKeys };\n}\n\n// =========================================================================\n// VersionNegotiation\n// =========================================================================\n\nexport function encodeVersionNegotiation(msg: PbVersionNegotiation): Uint8Array {\n const w = new ProtoWriter();\n w.writeBytes(1, msg.authKey);\n w.writeEnum(2, msg.direction);\n w.writeEnum(3, msg.minVersion);\n if (msg.chainParams !== undefined) {\n const sub = new ProtoWriter();\n sub.writeVarint(1, msg.chainParams.maxJump);\n sub.writeVarint(2, msg.chainParams.maxOooKeys);\n w.writeMessage(4, sub);\n }\n return w.finish();\n}\n\nexport function decodeVersionNegotiation(data: Uint8Array): PbVersionNegotiation {\n const r = new ProtoReader(data);\n let authKey: Uint8Array = EMPTY_BYTES;\n let direction = 0;\n let minVersion = 0;\n let chainParams: PbChainParams | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n authKey = r.readBytes();\n break;\n case 2:\n direction = r.readEnum();\n break;\n case 3:\n minVersion = r.readEnum();\n break;\n case 4:\n chainParams = decodeChainParams(r.readBytes());\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { authKey, direction, minVersion, chainParams };\n}\n\n// =========================================================================\n// EpochDirection\n// =========================================================================\n\nfunction encodeEpochDirection(w: ProtoWriter, msg: PbEpochDirection): void {\n w.writeVarint(1, msg.ctr);\n w.writeBytes(2, msg.next);\n w.writeBytes(3, msg.prev);\n}\n\nfunction decodeEpochDirection(r: ProtoReader): PbEpochDirection {\n let ctr = 0;\n let next: Uint8Array = EMPTY_BYTES;\n let prev: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n ctr = r.readVarint();\n break;\n case 2:\n next = r.readBytes();\n break;\n case 3:\n prev = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { ctr, next, prev };\n}\n\n// =========================================================================\n// Epoch\n// =========================================================================\n\nfunction encodeEpoch(msg: PbEpoch): Uint8Array {\n const w = new ProtoWriter();\n if (msg.send !== undefined) {\n const sub = new ProtoWriter();\n encodeEpochDirection(sub, msg.send);\n w.writeMessage(1, sub);\n }\n if (msg.recv !== undefined) {\n const sub = new ProtoWriter();\n encodeEpochDirection(sub, msg.recv);\n w.writeMessage(2, sub);\n }\n return w.finish();\n}\n\nfunction decodeEpoch(data: Uint8Array): PbEpoch {\n const r = new ProtoReader(data);\n let send: PbEpochDirection | undefined;\n let recv: PbEpochDirection | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n send = decodeEpochDirection(r.readMessage());\n break;\n case 2:\n recv = decodeEpochDirection(r.readMessage());\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { send, recv };\n}\n\n// =========================================================================\n// Chain\n// =========================================================================\n\nexport function encodeChain(msg: PbChain): Uint8Array {\n const w = new ProtoWriter();\n w.writeEnum(1, msg.direction);\n w.writeVarint(2, msg.currentEpoch);\n for (const link of msg.links) {\n w.writeBytes(3, encodeEpoch(link));\n }\n w.writeBytes(4, msg.nextRoot);\n w.writeVarint(5, msg.sendEpoch);\n if (msg.params !== undefined) {\n const sub = new ProtoWriter();\n sub.writeVarint(1, msg.params.maxJump);\n sub.writeVarint(2, msg.params.maxOooKeys);\n w.writeMessage(6, sub);\n }\n return w.finish();\n}\n\nexport function decodeChain(data: Uint8Array): PbChain {\n const r = new ProtoReader(data);\n let direction = 0;\n let currentEpoch = 0n;\n const links: PbEpoch[] = [];\n let nextRoot: Uint8Array = EMPTY_BYTES;\n let sendEpoch = 0n;\n let params: PbChainParams | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n direction = r.readEnum();\n break;\n case 2:\n currentEpoch = r.readVarint64();\n break;\n case 3:\n links.push(decodeEpoch(r.readBytes()));\n break;\n case 4:\n nextRoot = r.readBytes();\n break;\n case 5:\n sendEpoch = r.readVarint64();\n break;\n case 6:\n params = decodeChainParams(r.readBytes());\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { direction, currentEpoch, links, nextRoot, sendEpoch, params };\n}\n\n// =========================================================================\n// Authenticator\n// =========================================================================\n\nexport function encodeAuthenticator(msg: PbAuthenticator): Uint8Array {\n const w = new ProtoWriter();\n w.writeBytes(1, msg.rootKey);\n w.writeBytes(2, msg.macKey);\n return w.finish();\n}\n\nexport function decodeAuthenticator(data: Uint8Array): PbAuthenticator {\n const r = new ProtoReader(data);\n let rootKey: Uint8Array = EMPTY_BYTES;\n let macKey: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n rootKey = r.readBytes();\n break;\n case 2:\n macKey = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { rootKey, macKey };\n}\n\n// =========================================================================\n// PolynomialEncoder\n// =========================================================================\n\nexport function encodePolynomialEncoder(msg: PbPolynomialEncoder): Uint8Array {\n const w = new ProtoWriter();\n w.writeVarint(1, msg.idx);\n for (const pt of msg.pts) {\n w.writeBytes(2, pt);\n }\n for (const poly of msg.polys) {\n w.writeBytes(3, poly);\n }\n return w.finish();\n}\n\nexport function decodePolynomialEncoder(data: Uint8Array): PbPolynomialEncoder {\n const r = new ProtoReader(data);\n let idx = 0;\n const pts: Uint8Array[] = [];\n const polys: Uint8Array[] = [];\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n idx = r.readVarint();\n break;\n case 2:\n pts.push(r.readBytes());\n break;\n case 3:\n polys.push(r.readBytes());\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { idx, pts, polys };\n}\n\n// =========================================================================\n// PolynomialDecoder\n// =========================================================================\n\nexport function encodePolynomialDecoder(msg: PbPolynomialDecoder): Uint8Array {\n const w = new ProtoWriter();\n w.writeVarint(1, msg.ptsNeeded);\n w.writeVarint(2, msg.polys);\n for (const pt of msg.pts) {\n w.writeBytes(3, pt);\n }\n w.writeBool(4, msg.isComplete);\n return w.finish();\n}\n\nexport function decodePolynomialDecoder(data: Uint8Array): PbPolynomialDecoder {\n const r = new ProtoReader(data);\n let ptsNeeded = 0;\n let polys = 0;\n const pts: Uint8Array[] = [];\n let isComplete = false;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n ptsNeeded = r.readVarint();\n break;\n case 2:\n polys = r.readVarint();\n break;\n case 3:\n pts.push(r.readBytes());\n break;\n case 4:\n isComplete = r.readBool();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { ptsNeeded, polys, pts, isComplete };\n}\n\n// =========================================================================\n// Chunk\n// =========================================================================\n\nexport function encodeChunk(msg: PbChunk): Uint8Array {\n const w = new ProtoWriter();\n w.writeVarint(1, msg.index);\n w.writeBytes(2, msg.data);\n return w.finish();\n}\n\nexport function decodeChunk(data: Uint8Array): PbChunk {\n const r = new ProtoReader(data);\n let index = 0;\n let chunkData: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n index = r.readVarint();\n break;\n case 2:\n chunkData = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { index, data: chunkData };\n}\n\n// =========================================================================\n// V1Msg\n// =========================================================================\n\nexport function encodeV1Msg(msg: PbV1Msg): Uint8Array {\n const w = new ProtoWriter();\n w.writeVarint(1, msg.epoch);\n w.writeVarint(2, msg.index);\n if (msg.innerMsg !== undefined) {\n const inner = msg.innerMsg;\n switch (inner.type) {\n case \"hdr\": {\n const sub = new ProtoWriter();\n sub.writeVarint(1, inner.chunk.index);\n sub.writeBytes(2, inner.chunk.data);\n w.writeMessage(3, sub);\n break;\n }\n case \"ek\": {\n const sub = new ProtoWriter();\n sub.writeVarint(1, inner.chunk.index);\n sub.writeBytes(2, inner.chunk.data);\n w.writeMessage(4, sub);\n break;\n }\n case \"ekCt1Ack\": {\n const sub = new ProtoWriter();\n sub.writeVarint(1, inner.chunk.index);\n sub.writeBytes(2, inner.chunk.data);\n w.writeMessage(5, sub);\n break;\n }\n case \"ct1Ack\": {\n // Bool field at field 6\n w.writeBool(6, inner.value);\n break;\n }\n case \"ct1\": {\n const sub = new ProtoWriter();\n sub.writeVarint(1, inner.chunk.index);\n sub.writeBytes(2, inner.chunk.data);\n w.writeMessage(7, sub);\n break;\n }\n case \"ct2\": {\n const sub = new ProtoWriter();\n sub.writeVarint(1, inner.chunk.index);\n sub.writeBytes(2, inner.chunk.data);\n w.writeMessage(8, sub);\n break;\n }\n }\n }\n return w.finish();\n}\n\nexport function decodeV1Msg(data: Uint8Array): PbV1Msg {\n const r = new ProtoReader(data);\n let epoch = 0n;\n let index = 0;\n let innerMsg: PbV1MsgInner | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n epoch = r.readVarint64();\n break;\n case 2:\n index = r.readVarint();\n break;\n case 3:\n innerMsg = { type: \"hdr\", chunk: decodeChunk(r.readBytes()) };\n break;\n case 4:\n innerMsg = { type: \"ek\", chunk: decodeChunk(r.readBytes()) };\n break;\n case 5:\n innerMsg = { type: \"ekCt1Ack\", chunk: decodeChunk(r.readBytes()) };\n break;\n case 6:\n innerMsg = { type: \"ct1Ack\", value: r.readBool() };\n break;\n case 7:\n innerMsg = { type: \"ct1\", chunk: decodeChunk(r.readBytes()) };\n break;\n case 8:\n innerMsg = { type: \"ct2\", chunk: decodeChunk(r.readBytes()) };\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { epoch, index, innerMsg };\n}\n\n// =========================================================================\n// Unchunked state encode/decode helpers\n// =========================================================================\n\nfunction encodeAuthOptional(w: ProtoWriter, fieldNumber: number, auth?: PbAuthenticator): void {\n if (auth !== undefined) {\n const sub = new ProtoWriter();\n sub.writeBytes(1, auth.rootKey);\n sub.writeBytes(2, auth.macKey);\n w.writeMessage(fieldNumber, sub);\n }\n}\n\nfunction decodeAuthOptional(r: ProtoReader): PbAuthenticator {\n return decodeAuthenticator(r.readBytes());\n}\n\n/**\n * Detect whether an unchunked sub-message uses the Rust field layout\n * (epoch at field 1, auth at field 2, data fields shifted +1) or the\n * TS layout (auth at field 1, data fields as-is).\n *\n * Returns the field number offset: 0 for TS layout, 1 for Rust layout.\n * Detection is based on field 1's wire type:\n * - varint (wire type 0) => Rust layout (field 1 = epoch)\n * - length-delimited (wire type 2) => TS layout (field 1 = auth)\n */\nfunction detectUcLayout(data: Uint8Array): number {\n if (data.length === 0) return 0;\n // Read the first tag to check wire type\n const firstByte = data[0];\n const wireType = firstByte & 0x7;\n // Varint wire type 0 at field 1 => Rust layout (epoch)\n // Length-delimited wire type 2 at field 1 => TS layout (auth)\n return wireType === WIRE_VARINT ? 1 : 0;\n}\n\n// -- keysUnsampled (unchunked) --\n\nfunction encodeUcKeysUnsampled(msg: { auth?: PbAuthenticator | undefined }): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n return w.finish();\n}\n\nfunction decodeUcKeysUnsampled(data: Uint8Array): { auth?: PbAuthenticator | undefined } {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth };\n}\n\n// -- keysSampled (unchunked) --\n\nfunction encodeUcKeysSampled(msg: {\n auth?: PbAuthenticator | undefined;\n ek: Uint8Array;\n dk: Uint8Array;\n hdr: Uint8Array;\n hdrMac: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.ek);\n w.writeBytes(3, msg.dk);\n w.writeBytes(4, msg.hdr);\n w.writeBytes(5, msg.hdrMac);\n return w.finish();\n}\n\nfunction decodeUcKeysSampled(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n ek: Uint8Array;\n dk: Uint8Array;\n hdr: Uint8Array;\n hdrMac: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let ek: Uint8Array = EMPTY_BYTES;\n let dk: Uint8Array = EMPTY_BYTES;\n let hdr: Uint8Array = EMPTY_BYTES;\n let hdrMac: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n ek = r.readBytes();\n break;\n case 3:\n dk = r.readBytes();\n break;\n case 4:\n hdr = r.readBytes();\n break;\n case 5:\n hdrMac = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, ek, dk, hdr, hdrMac };\n}\n\n// -- headerSent (unchunked) --\n// NOTE: Rust uses Unchunked.EkSent for Chunked.HeaderSent:\n// Rust: epoch=1, auth=2, dk=3\n// TS: auth=1, ek=2, dk=3\n// The TS type carries ek+dk but Rust's EkSent only has dk.\n// The offset detection handles the epoch field difference.\n\nfunction encodeUcHeaderSent(msg: {\n auth?: PbAuthenticator | undefined;\n ek: Uint8Array;\n dk: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.ek);\n w.writeBytes(3, msg.dk);\n return w.finish();\n}\n\nfunction decodeUcHeaderSent(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n ek: Uint8Array;\n dk: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let ek: Uint8Array = EMPTY_BYTES;\n let dk: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n ek = r.readBytes();\n break;\n case 3:\n dk = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, ek, dk };\n}\n\n// -- ct1Received / ekSentCt1Received (unchunked, same shape) --\n\nfunction encodeUcDkCt1(msg: {\n auth?: PbAuthenticator | undefined;\n dk: Uint8Array;\n ct1: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.dk);\n w.writeBytes(3, msg.ct1);\n return w.finish();\n}\n\nfunction decodeUcDkCt1(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n dk: Uint8Array;\n ct1: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let dk: Uint8Array = EMPTY_BYTES;\n let ct1: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n dk = r.readBytes();\n break;\n case 3:\n ct1 = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, dk, ct1 };\n}\n\n// -- noHeaderReceived / ct2Sampled (unchunked, auth-only) --\n// Reuses encodeUcKeysUnsampled / decodeUcKeysUnsampled\n\n// -- headerReceived (unchunked) --\n// NOTE: Rust Unchunked.HeaderReceived has only {epoch, auth, hdr},\n// while TS carries {auth, hdr, es, ct1, ss}. The offset detection\n// handles the epoch field difference; extra fields (es, ct1, ss)\n// will be at shifted positions for Rust data.\n\nfunction encodeUcHeaderReceived(msg: {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ct1: Uint8Array;\n ss: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.hdr);\n w.writeBytes(3, msg.es);\n w.writeBytes(4, msg.ct1);\n w.writeBytes(5, msg.ss);\n return w.finish();\n}\n\nfunction decodeUcHeaderReceived(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ct1: Uint8Array;\n ss: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let hdr: Uint8Array = EMPTY_BYTES;\n let es: Uint8Array = EMPTY_BYTES;\n let ct1: Uint8Array = EMPTY_BYTES;\n let ss: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n hdr = r.readBytes();\n break;\n case 3:\n es = r.readBytes();\n break;\n case 4:\n ct1 = r.readBytes();\n break;\n case 5:\n ss = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, hdr, es, ct1, ss };\n}\n\n// -- ct1Sampled / ct1Acknowledged (unchunked, auth+hdr+es+ct1) --\n\nfunction encodeUcAuthHdrEsCt1(msg: {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ct1: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.hdr);\n w.writeBytes(3, msg.es);\n w.writeBytes(4, msg.ct1);\n return w.finish();\n}\n\nfunction decodeUcAuthHdrEsCt1(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ct1: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let hdr: Uint8Array = EMPTY_BYTES;\n let es: Uint8Array = EMPTY_BYTES;\n let ct1: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n hdr = r.readBytes();\n break;\n case 3:\n es = r.readBytes();\n break;\n case 4:\n ct1 = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, hdr, es, ct1 };\n}\n\n// -- ekReceivedCt1Sampled (unchunked, auth+hdr+es+ek+ct1) --\n\nfunction encodeUcEkReceivedCt1Sampled(msg: {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ek: Uint8Array;\n ct1: Uint8Array;\n}): Uint8Array {\n const w = new ProtoWriter();\n encodeAuthOptional(w, 1, msg.auth);\n w.writeBytes(2, msg.hdr);\n w.writeBytes(3, msg.es);\n w.writeBytes(4, msg.ek);\n w.writeBytes(5, msg.ct1);\n return w.finish();\n}\n\nfunction decodeUcEkReceivedCt1Sampled(data: Uint8Array): {\n auth?: PbAuthenticator | undefined;\n hdr: Uint8Array;\n es: Uint8Array;\n ek: Uint8Array;\n ct1: Uint8Array;\n} {\n const r = new ProtoReader(data);\n const offset = detectUcLayout(data);\n let auth: PbAuthenticator | undefined;\n let hdr: Uint8Array = EMPTY_BYTES;\n let es: Uint8Array = EMPTY_BYTES;\n let ek: Uint8Array = EMPTY_BYTES;\n let ct1: Uint8Array = EMPTY_BYTES;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n const fn = field.fieldNumber - offset;\n switch (fn) {\n case 1:\n auth = decodeAuthOptional(r);\n break;\n case 2:\n hdr = r.readBytes();\n break;\n case 3:\n es = r.readBytes();\n break;\n case 4:\n ek = r.readBytes();\n break;\n case 5:\n ct1 = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { auth, hdr, es, ek, ct1 };\n}\n\n// =========================================================================\n// Chunked state (wraps unchunked + encoder/decoder)\n// =========================================================================\n\n/**\n * Encode a PbChunkedState into a sub-message for V1State.\n * The field number in V1State determines which variant this is:\n * 1=keysUnsampled, 2=keysSampled, ..., 11=ct2Sampled\n *\n * Each chunked state has:\n * field 1 = unchunked data\n * field 2 = encoder (if present)\n * field 3 = decoder (if present)\n */\nfunction encodeChunkedStateInner(state: PbChunkedState): { fieldNumber: number; data: Uint8Array } {\n const w = new ProtoWriter();\n\n switch (state.type) {\n case \"keysUnsampled\": {\n w.writeBytes(1, encodeUcKeysUnsampled(state.uc));\n return { fieldNumber: 1, data: w.finish() };\n }\n case \"keysSampled\": {\n w.writeBytes(1, encodeUcKeysSampled(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingHdr));\n return { fieldNumber: 2, data: w.finish() };\n }\n case \"headerSent\": {\n w.writeBytes(1, encodeUcHeaderSent(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingEk));\n w.writeBytes(3, encodePolynomialDecoder(state.receivingCt1));\n return { fieldNumber: 3, data: w.finish() };\n }\n case \"ct1Received\": {\n w.writeBytes(1, encodeUcDkCt1(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingEk));\n return { fieldNumber: 4, data: w.finish() };\n }\n case \"ekSentCt1Received\": {\n w.writeBytes(1, encodeUcDkCt1(state.uc));\n w.writeBytes(3, encodePolynomialDecoder(state.receivingCt2));\n return { fieldNumber: 5, data: w.finish() };\n }\n case \"noHeaderReceived\": {\n w.writeBytes(1, encodeUcKeysUnsampled(state.uc));\n w.writeBytes(2, encodePolynomialDecoder(state.receivingHdr));\n return { fieldNumber: 6, data: w.finish() };\n }\n case \"headerReceived\": {\n w.writeBytes(1, encodeUcHeaderReceived(state.uc));\n w.writeBytes(2, encodePolynomialDecoder(state.receivingEk));\n return { fieldNumber: 7, data: w.finish() };\n }\n case \"ct1Sampled\": {\n w.writeBytes(1, encodeUcAuthHdrEsCt1(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingCt1));\n w.writeBytes(3, encodePolynomialDecoder(state.receivingEk));\n return { fieldNumber: 8, data: w.finish() };\n }\n case \"ekReceivedCt1Sampled\": {\n w.writeBytes(1, encodeUcEkReceivedCt1Sampled(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingCt1));\n return { fieldNumber: 9, data: w.finish() };\n }\n case \"ct1Acknowledged\": {\n w.writeBytes(1, encodeUcAuthHdrEsCt1(state.uc));\n w.writeBytes(2, encodePolynomialDecoder(state.receivingEk));\n return { fieldNumber: 10, data: w.finish() };\n }\n case \"ct2Sampled\": {\n w.writeBytes(1, encodeUcKeysUnsampled(state.uc));\n w.writeBytes(2, encodePolynomialEncoder(state.sendingCt2));\n return { fieldNumber: 11, data: w.finish() };\n }\n }\n}\n\ninterface ChunkedDecodeResult {\n uc: Uint8Array;\n encoder?: Uint8Array | undefined;\n decoder?: Uint8Array | undefined;\n}\n\nfunction decodeChunkedRaw(data: Uint8Array): ChunkedDecodeResult {\n const r = new ProtoReader(data);\n let uc: Uint8Array = EMPTY_BYTES;\n let encoder: Uint8Array | undefined;\n let decoder: Uint8Array | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n uc = r.readBytes();\n break;\n case 2:\n encoder = r.readBytes();\n break;\n case 3:\n decoder = r.readBytes();\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { uc, encoder, decoder };\n}\n\nfunction requireField(data: Uint8Array | undefined, name: string): Uint8Array {\n if (data === undefined) {\n throw new Error(`Protobuf: missing required field '${name}'`);\n }\n return data;\n}\n\nfunction decodeChunkedState(fieldNumber: number, data: Uint8Array): PbChunkedState {\n const raw = decodeChunkedRaw(data);\n\n switch (fieldNumber) {\n case 1:\n return { type: \"keysUnsampled\", uc: decodeUcKeysUnsampled(raw.uc) };\n case 2:\n return {\n type: \"keysSampled\",\n uc: decodeUcKeysSampled(raw.uc),\n sendingHdr: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n };\n case 3:\n return {\n type: \"headerSent\",\n uc: decodeUcHeaderSent(raw.uc),\n sendingEk: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n receivingCt1: decodePolynomialDecoder(requireField(raw.decoder, \"decoder\")),\n };\n case 4:\n return {\n type: \"ct1Received\",\n uc: decodeUcDkCt1(raw.uc),\n sendingEk: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n };\n case 5:\n return {\n type: \"ekSentCt1Received\",\n uc: decodeUcDkCt1(raw.uc),\n receivingCt2: decodePolynomialDecoder(requireField(raw.decoder, \"decoder\")),\n };\n case 6:\n return {\n type: \"noHeaderReceived\",\n uc: decodeUcKeysUnsampled(raw.uc),\n receivingHdr: decodePolynomialDecoder(requireField(raw.encoder, \"encoder\")),\n };\n case 7:\n return {\n type: \"headerReceived\",\n uc: decodeUcHeaderReceived(raw.uc),\n receivingEk: decodePolynomialDecoder(requireField(raw.encoder, \"encoder\")),\n };\n case 8:\n return {\n type: \"ct1Sampled\",\n uc: decodeUcAuthHdrEsCt1(raw.uc),\n sendingCt1: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n receivingEk: decodePolynomialDecoder(requireField(raw.decoder, \"decoder\")),\n };\n case 9:\n return {\n type: \"ekReceivedCt1Sampled\",\n uc: decodeUcEkReceivedCt1Sampled(raw.uc),\n sendingCt1: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n };\n case 10:\n return {\n type: \"ct1Acknowledged\",\n uc: decodeUcAuthHdrEsCt1(raw.uc),\n receivingEk: decodePolynomialDecoder(requireField(raw.encoder, \"encoder\")),\n };\n case 11:\n return {\n type: \"ct2Sampled\",\n uc: decodeUcKeysUnsampled(raw.uc),\n sendingCt2: decodePolynomialEncoder(requireField(raw.encoder, \"encoder\")),\n };\n default:\n throw new Error(`Unknown chunked state field number: ${fieldNumber}`);\n }\n}\n\n// =========================================================================\n// V1State\n// =========================================================================\n\nfunction encodeV1State(msg: PbV1State): Uint8Array {\n if (msg.innerState === undefined) return EMPTY_BYTES;\n const { fieldNumber, data } = encodeChunkedStateInner(msg.innerState);\n const w = new ProtoWriter();\n // Write as length-delimited sub-message at the correct oneof field number\n w.writeBytes(fieldNumber, data);\n // Field 12: epoch (used for deserialization round-trip)\n if (msg.epoch !== undefined) {\n w.writeVarint(12, msg.epoch);\n }\n return w.finish();\n}\n\nfunction decodeV1State(data: Uint8Array): PbV1State {\n const r = new ProtoReader(data);\n let innerState: PbChunkedState | undefined;\n let epoch: bigint | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n if (field.fieldNumber >= 1 && field.fieldNumber <= 11) {\n innerState = decodeChunkedState(field.fieldNumber, r.readBytes());\n } else if (field.fieldNumber === 12) {\n epoch = r.readVarint64();\n } else {\n r.skip(field.wireType);\n }\n }\n return { innerState, epoch };\n}\n\n// =========================================================================\n// PqRatchetState (top-level)\n// =========================================================================\n\nexport function encodePqRatchetState(msg: PbPqRatchetState): Uint8Array {\n const w = new ProtoWriter();\n if (msg.versionNegotiation !== undefined) {\n w.writeBytes(1, encodeVersionNegotiation(msg.versionNegotiation));\n }\n if (msg.chain !== undefined) {\n w.writeBytes(2, encodeChain(msg.chain));\n }\n if (msg.v1 !== undefined) {\n w.writeBytes(3, encodeV1State(msg.v1));\n }\n return w.finish();\n}\n\nexport function decodePqRatchetState(data: Uint8Array): PbPqRatchetState {\n const r = new ProtoReader(data);\n let versionNegotiation: PbVersionNegotiation | undefined;\n let chain: PbChain | undefined;\n let v1: PbV1State | undefined;\n while (!r.done) {\n const field = r.readField();\n if (field === null) break;\n switch (field.fieldNumber) {\n case 1:\n versionNegotiation = decodeVersionNegotiation(r.readBytes());\n break;\n case 2:\n chain = decodeChain(r.readBytes());\n break;\n case 3:\n v1 = decodeV1State(r.readBytes());\n break;\n default:\n r.skip(field.wireType);\n }\n }\n return { versionNegotiation, chain, v1 };\n}\n\n// =========================================================================\n// Re-exports\n// =========================================================================\n\nexport type {\n PbAuthenticator,\n PbChain,\n PbChainParams,\n PbChunk,\n PbChunkedState,\n PbEpoch,\n PbEpochDirection,\n PbPolynomialDecoder,\n PbPolynomialEncoder,\n PbPqRatchetState,\n PbV1Msg,\n PbV1MsgInner,\n PbV1State,\n PbVersionNegotiation,\n} from \"./pq-ratchet-types.js\";\n","/**\n * Copyright © 2025 Signal Messenger, LLC\n * Copyright © 2026 Parity Technologies\n *\n * Top-level public API for the SPQR protocol.\n *\n * Matches Signal's Rust `lib.rs` interface. All state is serialized as\n * opaque protobuf bytes (Uint8Array) so that callers never need to touch\n * internal types.\n *\n * Exported functions:\n * - emptyState() -> empty serialized state (V0)\n * - initialState(p) -> create initial serialized state\n * - send(state, rng) -> produce next message + advance state\n * - recv(state, msg) -> consume incoming message + advance state\n * - currentVersion(s) -> inspect version negotiation status\n */\n\nimport {\n type States,\n initA,\n initB,\n send as chunkedSend,\n recv as chunkedRecv,\n} from \"./v1/chunked/index.js\";\nimport { serializeMessage, deserializeMessage } from \"./v1/chunked/message.js\";\nimport { statesToPb, statesFromPb } from \"./v1/chunked/serialize.js\";\nimport { Chain } from \"./chain.js\";\nimport { encodePqRatchetState, decodePqRatchetState } from \"./proto/index.js\";\nimport type { PbPqRatchetState, PbVersionNegotiation } from \"./proto/pq-ratchet-types.js\";\nimport { SpqrError, SpqrErrorCode } from \"./error.js\";\nimport {\n Version,\n Direction,\n type Params,\n type Secret,\n type Send,\n type Recv,\n type CurrentVersion,\n type SerializedState,\n type SerializedMessage,\n type RandomBytes,\n type ChainParams,\n} from \"./types.js\";\n\n// Re-export public types\nexport {\n Version,\n Direction,\n type Params,\n type Secret,\n type Send,\n type Recv,\n type CurrentVersion,\n type SerializedState,\n type SerializedMessage,\n type RandomBytes,\n type ChainParams,\n};\nexport { SpqrError, SpqrErrorCode } from \"./error.js\";\n\n// ---------------------------------------------------------------------------\n// emptyState\n// ---------------------------------------------------------------------------\n\n/**\n * Return an empty (V0) serialized state.\n */\nexport function emptyState(): SerializedState {\n return new Uint8Array(0);\n}\n\n// ---------------------------------------------------------------------------\n// initialState\n// ---------------------------------------------------------------------------\n\n/**\n * Create an initial serialized state from parameters.\n *\n * For V0, returns an empty state. For V1+, initializes the inner V1\n * state machine and version negotiation.\n */\nexport function initialState(params: Params): SerializedState {\n if (params.version === Version.V0) {\n return emptyState();\n }\n\n // Initialize the V1 inner state\n const inner = initInner(params.version, params.direction, params.authKey);\n\n // Build version negotiation\n const versionNegotiation: PbVersionNegotiation = {\n authKey: Uint8Array.from(params.authKey),\n direction: params.direction,\n minVersion: params.minVersion,\n chainParams: {\n maxJump: params.chainParams.maxJump,\n maxOooKeys: params.chainParams.maxOooKeys,\n },\n };\n\n const pbState: PbPqRatchetState = {\n versionNegotiation,\n chain: undefined,\n v1: inner,\n };\n\n return encodePqRatchetState(pbState);\n}\n\n// ---------------------------------------------------------------------------\n// send\n// ---------------------------------------------------------------------------\n\n/**\n * Produce the next outgoing message from the current state.\n *\n * Returns the updated state, serialized message, and optional message key.\n */\nexport function send(state: SerializedState, rng: RandomBytes): Send {\n // V0: empty state passthrough\n if (state.length === 0) {\n return { state: new Uint8Array(0), msg: new Uint8Array(0), key: null };\n }\n\n const statePb = decodePqRatchetState(state);\n\n if (statePb.v1 === undefined) {\n // No V1 inner => V0\n return { state: new Uint8Array(0), msg: new Uint8Array(0), key: null };\n }\n\n // Deserialize runtime states from protobuf\n const runtimeStates = statesFromPb(statePb.v1);\n\n // Execute the chunked send\n const sendResult = chunkedSend(runtimeStates, rng);\n\n // Get or create chain\n let chain: Chain | undefined;\n if (statePb.chain !== undefined) {\n chain = Chain.fromProto(statePb.chain);\n } else if (statePb.versionNegotiation !== undefined) {\n const vn = statePb.versionNegotiation;\n if ((vn.minVersion as Version) > Version.V0) {\n chain = chainFromVersionNegotiation(vn);\n }\n } else {\n throw new SpqrError(\n \"Chain not available and no version negotiation\",\n SpqrErrorCode.ChainNotAvailable,\n );\n }\n\n let index: number;\n let msgKey: Uint8Array;\n let chainPb: typeof statePb.chain;\n\n if (chain === undefined) {\n // No chain (min_version === V0, still negotiating)\n if (sendResult.key !== null) {\n // Should not happen in V0 min_version case during negotiation\n throw new SpqrError(\"Unexpected epoch secret without chain\", SpqrErrorCode.ChainNotAvailable);\n }\n index = 0;\n msgKey = new Uint8Array(0);\n chainPb = undefined;\n } else {\n if (sendResult.key !== null) {\n // Epoch secret epoch matches chain expectation:\n // state machine epoch N maps directly to chain addEpoch(N)\n // since chain.currentEpoch starts at 0 and expects N = currentEpoch + 1\n chain.addEpoch(sendResult.key);\n }\n const msgEpoch = sendResult.msg.epoch - 1n;\n const [sendIndex, sendKey] = chain.sendKey(msgEpoch);\n index = sendIndex;\n msgKey = sendKey;\n chainPb = chain.toProto();\n }\n\n // Serialize message\n const serializedMsg = serializeMessage(sendResult.msg, index);\n\n // Serialize updated state\n const v1Pb = statesToPb(sendResult.state);\n const newStatePb: PbPqRatchetState = {\n versionNegotiation: statePb.versionNegotiation, // preserved on send\n chain: chainPb,\n v1: v1Pb,\n };\n\n return {\n state: encodePqRatchetState(newStatePb),\n msg: serializedMsg,\n key: msgKey.length === 0 ? null : msgKey,\n };\n}\n\n// ---------------------------------------------------------------------------\n// recv\n// ---------------------------------------------------------------------------\n\n/**\n * Process an incoming message and transition the state.\n *\n * Returns the updated state and optional message key.\n */\nexport function recv(state: SerializedState, msg: SerializedMessage): Recv {\n // V0: empty state passthrough\n if (state.length === 0 && msg.length === 0) {\n return { state: new Uint8Array(0), key: null };\n }\n\n // Decode the pre-negotiated state\n const prenegotiatedPb =\n state.length === 0\n ? ({ v1: undefined, chain: undefined, versionNegotiation: undefined } as PbPqRatchetState)\n : decodePqRatchetState(state);\n\n // Determine message version\n const msgVer = msgVersion(msg);\n if (msgVer === undefined) {\n // Unknown version, ignore the message\n return { state: Uint8Array.from(state), key: null };\n }\n\n const stateVer = stateVersion(prenegotiatedPb);\n\n // Version negotiation\n let statePb: PbPqRatchetState;\n if (msgVer >= stateVer) {\n // Equal or greater version -- proceed with current state\n statePb = prenegotiatedPb;\n } else {\n // Message version < state version -- negotiate down\n const vn = prenegotiatedPb.versionNegotiation;\n if (vn === undefined) {\n throw new SpqrError(\n `Version mismatch: state=${stateVer}, msg=${msgVer}, no negotiation available`,\n SpqrErrorCode.VersionMismatch,\n );\n }\n if (msgVer < (vn.minVersion as Version)) {\n throw new SpqrError(\n `Minimum version not met: min=${vn.minVersion}, msg=${msgVer}`,\n SpqrErrorCode.MinimumVersion,\n );\n }\n\n // Negotiate down to the message version\n const inner = initInner(msgVer, vn.direction as Direction, Uint8Array.from(vn.authKey));\n const chainResult = chainFrom(prenegotiatedPb.chain, vn);\n statePb = {\n v1: inner,\n versionNegotiation: undefined, // disallow further negotiation\n chain: chainResult,\n };\n }\n\n // Process the message\n if (statePb.v1 === undefined) {\n // V0 state\n return { state: new Uint8Array(0), key: null };\n }\n\n // Deserialize the message\n const { msg: sckaMsg, index } = deserializeMessage(msg);\n\n // Deserialize runtime states from protobuf\n const runtimeStates = statesFromPb(statePb.v1);\n\n // Execute the chunked recv\n const recvResult = chunkedRecv(runtimeStates, sckaMsg);\n\n // Chain key derivation\n const msgKeyEpoch = sckaMsg.epoch - 1n;\n const chainObj = chainFromState(statePb.chain, statePb.versionNegotiation);\n\n if (recvResult.key !== null) {\n // Epoch secret epoch matches chain expectation directly\n chainObj.addEpoch(recvResult.key);\n }\n\n let msgKey: Uint8Array;\n if (msgKeyEpoch === 0n && index === 0) {\n // First message has no chain key\n msgKey = new Uint8Array(0);\n } else {\n msgKey = chainObj.recvKey(msgKeyEpoch, index);\n }\n\n // Serialize the updated state\n const v1Pb = statesToPb(recvResult.state);\n const newStatePb: PbPqRatchetState = {\n versionNegotiation: undefined, // cleared on recv\n chain: chainObj.toProto(),\n v1: v1Pb,\n };\n\n return {\n state: encodePqRatchetState(newStatePb),\n key: msgKey.length === 0 ? null : msgKey,\n };\n}\n\n// ---------------------------------------------------------------------------\n// currentVersion\n// ---------------------------------------------------------------------------\n\n/**\n * Inspect the current version negotiation status of a serialized state.\n */\nexport function currentVersion(state: SerializedState): CurrentVersion {\n if (state.length === 0) {\n return { type: \"negotiation_complete\", version: Version.V0 };\n }\n\n const statePb = decodePqRatchetState(state);\n const version = statePb.v1 !== undefined ? Version.V1 : Version.V0;\n\n if (statePb.versionNegotiation !== undefined) {\n return {\n type: \"still_negotiating\",\n version,\n minVersion: statePb.versionNegotiation.minVersion as Version,\n };\n }\n return { type: \"negotiation_complete\", version };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Initialize the V1 inner state based on version and direction.\n */\nfunction initInner(\n version: Version,\n direction: Direction,\n authKey: Uint8Array,\n): PbPqRatchetState[\"v1\"] {\n if (version === Version.V0) {\n return undefined;\n }\n\n // V1\n let states: States;\n if (direction === Direction.A2B) {\n states = initA(authKey);\n } else {\n states = initB(authKey);\n }\n return statesToPb(states);\n}\n\n/**\n * Extract version from a serialized message.\n * Empty msg -> V0. msg[0]: 0 -> V0, 1 -> V1, else undefined.\n */\nfunction msgVersion(msg: SerializedMessage): Version | undefined {\n if (msg.length === 0) return Version.V0;\n const v = msg[0];\n if (v === 0) return Version.V0;\n if (v === 1) return Version.V1;\n return undefined;\n}\n\n/**\n * Extract version from the decoded state.\n * No v1 inner -> V0. Has v1 inner -> V1.\n */\nfunction stateVersion(state: PbPqRatchetState): Version {\n return state.v1 !== undefined ? Version.V1 : Version.V0;\n}\n\n/**\n * Create a Chain from version negotiation parameters.\n */\nfunction chainFromVersionNegotiation(vn: PbVersionNegotiation): Chain {\n const chainParams: ChainParams = vn.chainParams ?? {\n maxJump: 25000,\n maxOooKeys: 2000,\n };\n return Chain.create(Uint8Array.from(vn.authKey), vn.direction as Direction, chainParams);\n}\n\n/**\n * Get or create a Chain from the existing chain proto and version negotiation.\n * Prefers existing chain, falls back to creating from version negotiation.\n */\nfunction chainFrom(\n chainPb: PbPqRatchetState[\"chain\"],\n vn: PbVersionNegotiation | undefined,\n): PbPqRatchetState[\"chain\"] {\n if (chainPb !== undefined) return chainPb;\n if (vn !== undefined) return chainFromVersionNegotiation(vn).toProto();\n return undefined;\n}\n\n/**\n * Get a Chain object from state, creating from vn if needed.\n */\nfunction chainFromState(\n chainPb: PbPqRatchetState[\"chain\"],\n vn: PbVersionNegotiation | undefined,\n): Chain {\n if (chainPb !== undefined) return Chain.fromProto(chainPb);\n if (vn !== undefined) return chainFromVersionNegotiation(vn);\n throw new SpqrError(\n \"Chain not available and no version negotiation\",\n SpqrErrorCode.ChainNotAvailable,\n );\n}\n"],"mappings":"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"}