Sign In

@quantakrypto/sieve

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@quantakrypto/sieve - npm Package Compare versions

Comparing version
0.4.4
to
0.5.0
+1
-1
dist/categories/index.d.ts

@@ -18,3 +18,3 @@ /**

/** A named, family-scoped category. */
export interface RegisteredCategory {
interface RegisteredCategory {
name: string;

@@ -21,0 +21,0 @@ family: Family | "any";

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/categories/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,cAAc,YAAY,CAAC;AAE3B,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,4CAA4C;AAC5C,eAAO,MAAM,UAAU,EAAE,SAAS,kBAAkB,EAUnD,CAAC;AAEF,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,kBAAkB,EAAE,CAM1F;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/categories/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,cAAc,YAAY,CAAC;AAE3B,uCAAuC;AACvC,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,4CAA4C;AAC5C,eAAO,MAAM,UAAU,EAAE,SAAS,kBAAkB,EAUnD,CAAC;AAEF,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,kBAAkB,EAAE,CAM1F;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/categories/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,cAAc,YAAY,CAAC;AAW3B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAkC;IACvD,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE;IAC5E,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE;IAC5E,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,EAAE;IACzF,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE;IAC1E,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE;IACpE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;IACzD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE;CACpE,CAAC;AAEF,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,aAAsB;IAClE,OAAO,UAAU,CAAC,MAAM,CACtB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC;QAC3C,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,aAAa,CAAC,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC","sourcesContent":["/**\n * Category registry. Each entry is selected by family so the runner only\n * executes categories relevant to the parameter set under test.\n */\n\nimport type { Category } from \"./types.js\";\nimport type { Family } from \"../sizes.js\";\n\nimport { correctness } from \"./correctness.js\";\nimport { determinism } from \"./determinism.js\";\nimport { implicitRejection } from \"./implicit-rejection.js\";\nimport { sizes } from \"./sizes.js\";\nimport { robustness } from \"./robustness.js\";\nimport { dsa } from \"./dsa.js\";\nimport { slhDsa } from \"./slh-dsa.js\";\nimport { kat } from \"./kat.js\";\nimport { timing } from \"./timing.js\";\n\nexport * from \"./types.js\";\n\n/** A named, family-scoped category. */\nexport interface RegisteredCategory {\n name: string;\n family: Family | \"any\";\n /** Whether the category runs by default (timing is opt-in). */\n defaultOn: boolean;\n run: Category;\n}\n\n/** The full catalog, in execution order. */\nexport const CATEGORIES: readonly RegisteredCategory[] = [\n { name: \"correctness\", family: \"ml-kem\", defaultOn: true, run: correctness },\n { name: \"determinism\", family: \"ml-kem\", defaultOn: true, run: determinism },\n { name: \"implicit-rejection\", family: \"ml-kem\", defaultOn: true, run: implicitRejection },\n { name: \"sizes\", family: \"ml-kem\", defaultOn: true, run: sizes },\n { name: \"robustness\", family: \"ml-kem\", defaultOn: true, run: robustness },\n { name: \"dsa\", family: \"ml-dsa\", defaultOn: true, run: dsa },\n { name: \"slh-dsa\", family: \"slh-dsa\", defaultOn: true, run: slhDsa },\n { name: \"kat\", family: \"any\", defaultOn: true, run: kat },\n { name: \"timing\", family: \"ml-kem\", defaultOn: false, run: timing },\n];\n\n/** Categories applicable to a family (plus family-agnostic ones). */\nexport function categoriesFor(family: Family, includeTiming: boolean): RegisteredCategory[] {\n return CATEGORIES.filter(\n (c) =>\n (c.family === family || c.family === \"any\") &&\n (c.defaultOn || (c.name === \"timing\" && includeTiming)),\n );\n}\n\nexport { correctness, determinism, implicitRejection, sizes, robustness, dsa, slhDsa, kat, timing };\n"]}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/categories/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,cAAc,YAAY,CAAC;AAW3B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAkC;IACvD,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE;IAC5E,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE;IAC5E,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,EAAE;IACzF,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;IAChE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE;IAC1E,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE;IACpE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;IACzD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE;CACpE,CAAC;AAEF,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,aAAsB;IAClE,OAAO,UAAU,CAAC,MAAM,CACtB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC;QAC3C,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,aAAa,CAAC,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC","sourcesContent":["/**\n * Category registry. Each entry is selected by family so the runner only\n * executes categories relevant to the parameter set under test.\n */\n\nimport type { Category } from \"./types.js\";\nimport type { Family } from \"../sizes.js\";\n\nimport { correctness } from \"./correctness.js\";\nimport { determinism } from \"./determinism.js\";\nimport { implicitRejection } from \"./implicit-rejection.js\";\nimport { sizes } from \"./sizes.js\";\nimport { robustness } from \"./robustness.js\";\nimport { dsa } from \"./dsa.js\";\nimport { slhDsa } from \"./slh-dsa.js\";\nimport { kat } from \"./kat.js\";\nimport { timing } from \"./timing.js\";\n\nexport * from \"./types.js\";\n\n/** A named, family-scoped category. */\ninterface RegisteredCategory {\n name: string;\n family: Family | \"any\";\n /** Whether the category runs by default (timing is opt-in). */\n defaultOn: boolean;\n run: Category;\n}\n\n/** The full catalog, in execution order. */\nexport const CATEGORIES: readonly RegisteredCategory[] = [\n { name: \"correctness\", family: \"ml-kem\", defaultOn: true, run: correctness },\n { name: \"determinism\", family: \"ml-kem\", defaultOn: true, run: determinism },\n { name: \"implicit-rejection\", family: \"ml-kem\", defaultOn: true, run: implicitRejection },\n { name: \"sizes\", family: \"ml-kem\", defaultOn: true, run: sizes },\n { name: \"robustness\", family: \"ml-kem\", defaultOn: true, run: robustness },\n { name: \"dsa\", family: \"ml-dsa\", defaultOn: true, run: dsa },\n { name: \"slh-dsa\", family: \"slh-dsa\", defaultOn: true, run: slhDsa },\n { name: \"kat\", family: \"any\", defaultOn: true, run: kat },\n { name: \"timing\", family: \"ml-kem\", defaultOn: false, run: timing },\n];\n\n/** Categories applicable to a family (plus family-agnostic ones). */\nexport function categoriesFor(family: Family, includeTiming: boolean): RegisteredCategory[] {\n return CATEGORIES.filter(\n (c) =>\n (c.family === family || c.family === \"any\") &&\n (c.defaultOn || (c.name === \"timing\" && includeTiming)),\n );\n}\n\nexport { correctness, determinism, implicitRejection, sizes, robustness, dsa, slhDsa, kat, timing };\n"]}

@@ -1,1 +0,1 @@

{"version":3,"file":"kat.d.ts","sourceRoot":"","sources":["../../src/categories/kat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,KAAK,QAAQ,EAOd,MAAM,YAAY,CAAC;AAKpB,eAAO,MAAM,GAAG,EAAE,QAmFjB,CAAC"}
{"version":3,"file":"kat.d.ts","sourceRoot":"","sources":["../../src/categories/kat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,KAAK,QAAQ,EAOd,MAAM,YAAY,CAAC;AAKpB,eAAO,MAAM,GAAG,EAAE,QA+FjB,CAAC"}

@@ -63,2 +63,3 @@ /**

let okCount = 0;
let skipCount = 0;
let idx = 0;

@@ -69,3 +70,9 @@ for (const v of relevant) {

const result = await checkVector(ctx, v);
if (result.ok) {
if (result.skipped) {
// Unverifiable (e.g. a keygen vector with no seed) — NOT a match. Record it as
// a skip so it can't inflate the "matched" count into a false conformance pass.
skipCount++;
checks.push(skip(`${v.kind}[${idx}]`, result.detail));
}
else if (result.ok) {
okCount++;

@@ -82,5 +89,12 @@ // Keep the report compact: don't push a pass per vector.

}
// Denominator is the number of ACTUALLY-verified vectors, excluding skips.
const verified = relevant.length - skipCount;
if (okCount > 0) {
checks.push(pass("kat", `${okCount}/${relevant.length} ${param} vectors matched expected values`));
checks.push(pass("kat", `${okCount}/${verified} ${param} vectors matched expected values`));
}
else if (skipCount > 0) {
// Everything relevant was unverifiable — say so explicitly rather than passing on
// zero comparisons.
checks.push(skip("kat", `all ${skipCount} ${param} vector(s) were unverifiable (no seed/coins)`));
}
const status = rollUp(checks);

@@ -102,3 +116,3 @@ return {

if (!v.seed)
return { ok: true, detail: "no seed; skipped" };
return { ok: false, skipped: true, detail: "no seed; skipped" };
const resp = await runner.send({

@@ -124,3 +138,3 @@ family: "ml-kem",

if (!v.coins)
return { ok: true, detail: "no coins; skipped" };
return { ok: false, skipped: true, detail: "no coins; skipped" };
const resp = await runner.send({

@@ -127,0 +141,0 @@ family: "ml-kem",

@@ -1,1 +0,1 @@

{"version":3,"file":"kat.js","sourceRoot":"","sources":["../../src/categories/kat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * KAT category — Known-Answer Tests against OFFICIAL NIST ACVP vectors.\n *\n * This category is SKIPPED unless the user supplies `--vectors <dir>` with real\n * ACVP files. Sieve never fabricates expected values; if no vectors are\n * present, every check is a `skip` with a clear message pointing at\n * vectors/README.md.\n *\n * What we check when vectors ARE present:\n * - kem-keygen: if a seed is given, deterministic keygen must reproduce the\n * expected pk/sk exactly. (Skipped if the SUT can't do seeded keygen.)\n * - kem-encap: if coins are given, deterministic encaps must reproduce ct/ss.\n * - kem-decap: decaps(sk, ct) must equal the expected ss exactly.\n * - dsa-verify: verify(pk, msg, sig) must equal the expected verdict.\n *\n * These ARE exact-value assertions — but the expected bytes come from the\n * user's NIST files, not from Sieve.\n */\n\nimport {\n type Category,\n type CategoryResult,\n type Check,\n fail,\n pass,\n rollUp,\n skip,\n} from \"./types.js\";\nimport { bytesEqual } from \"./helpers.js\";\nimport { fromB64, toB64 } from \"../protocol.js\";\nimport { loadVectors, type Vector } from \"../vectors.js\";\n\nexport const kat: Category = async (ctx): Promise<CategoryResult> => {\n if (!ctx.vectorsDir) {\n return {\n category: \"kat\",\n status: \"skip\",\n checks: [\n skip(\n \"vectors\",\n \"no --vectors <dir> supplied; Sieve ships no test vectors and will not \" +\n \"fabricate them. See vectors/README.md to obtain official NIST ACVP files.\",\n ),\n ],\n summary: \"skipped — no official vectors provided\",\n };\n }\n\n const checks: Check[] = [];\n let loaded: ReturnType<typeof loadVectors>;\n try {\n loaded = loadVectors(ctx.vectorsDir);\n } catch (err) {\n return {\n category: \"kat\",\n status: \"fail\",\n checks: [\n fail(\"load\", `could not load vectors from ${ctx.vectorsDir}: ${(err as Error).message}`),\n ],\n summary: \"vector load failed\",\n };\n }\n\n for (const note of loaded.notes.slice(0, 10)) {\n checks.push(skip(\"note\", note));\n }\n\n // Only run vectors matching the parameter set under test.\n const param = ctx.sizes.id;\n const relevant = loaded.vectors.filter((v) => v.param === param);\n if (relevant.length === 0) {\n checks.push(\n skip(\n \"applicable\",\n `loaded ${loaded.vectors.length} vector(s) from ${loaded.files.length} file(s), ` +\n `but none for ${param}`,\n ),\n );\n const status = rollUp(checks);\n return { category: \"kat\", status, checks, summary: `no ${param} vectors among supplied files` };\n }\n\n let okCount = 0;\n let idx = 0;\n for (const v of relevant) {\n idx++;\n try {\n const result = await checkVector(ctx, v);\n if (result.ok) {\n okCount++;\n // Keep the report compact: don't push a pass per vector.\n } else {\n checks.push(fail(`${v.kind}[${idx}]`, result.detail, undefined));\n }\n } catch (err) {\n checks.push(fail(`${v.kind}[${idx}]`, `harness error: ${(err as Error).message}`));\n }\n }\n\n if (okCount > 0) {\n checks.push(\n pass(\"kat\", `${okCount}/${relevant.length} ${param} vectors matched expected values`),\n );\n }\n\n const status = rollUp(checks);\n return {\n category: \"kat\",\n status,\n checks,\n summary:\n status === \"pass\"\n ? `${okCount} ${param} KAT vectors passed`\n : `${checks.filter((c) => c.status === \"fail\").length} KAT mismatch(es)`,\n };\n};\n\ninterface VectorResult {\n ok: boolean;\n detail: string;\n}\n\nasync function checkVector(\n ctx: import(\"./types.js\").CategoryContext,\n v: Vector,\n): Promise<VectorResult> {\n const { runner } = ctx;\n const param = v.param;\n\n switch (v.kind) {\n case \"kem-keygen\": {\n if (!v.seed) return { ok: true, detail: \"no seed; skipped\" };\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"keygen\",\n seed: toB64(v.seed),\n });\n if (resp.ok !== true || !(\"pk\" in resp) || !(\"sk\" in resp)) {\n return {\n ok: false,\n detail: \"seeded keygen did not return pk/sk (SUT may not support seeds)\",\n };\n }\n const pkOk = bytesEqual(fromB64(resp.pk), v.pk);\n const skOk = bytesEqual(fromB64(resp.sk), v.sk);\n return pkOk && skOk\n ? { ok: true, detail: \"pk/sk match\" }\n : { ok: false, detail: `seeded keygen mismatch (pkOk=${pkOk}, skOk=${skOk})` };\n }\n case \"kem-encap\": {\n if (!v.coins) return { ok: true, detail: \"no coins; skipped\" };\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"encaps\",\n pk: toB64(v.pk),\n coins: toB64(v.coins),\n });\n if (resp.ok !== true || !(\"ct\" in resp) || !(\"ss\" in resp)) {\n return {\n ok: false,\n detail: \"deterministic encaps did not return ct/ss (SUT may not support coins)\",\n };\n }\n const ctOk = bytesEqual(fromB64(resp.ct), v.ct);\n const ssOk = bytesEqual(fromB64(resp.ss), v.ss);\n return ctOk && ssOk\n ? { ok: true, detail: \"ct/ss match\" }\n : { ok: false, detail: `encaps mismatch (ctOk=${ctOk}, ssOk=${ssOk})` };\n }\n case \"kem-decap\": {\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"decaps\",\n sk: toB64(v.sk),\n ct: toB64(v.ct),\n });\n if (resp.ok !== true || !(\"ss\" in resp)) {\n return { ok: false, detail: \"decaps did not return ss\" };\n }\n return bytesEqual(fromB64(resp.ss), v.ss)\n ? { ok: true, detail: \"ss matches\" }\n : { ok: false, detail: \"decaps shared secret does not match expected\" };\n }\n case \"dsa-verify\": {\n const resp = await runner.send({\n family: \"ml-dsa\",\n param,\n op: \"verify\",\n pk: toB64(v.pk),\n msg: toB64(v.msg),\n sig: toB64(v.sig),\n });\n if (resp.ok !== true || !(\"valid\" in resp)) {\n return { ok: false, detail: \"verify did not return a 'valid' verdict\" };\n }\n return resp.valid === v.expected\n ? { ok: true, detail: `verdict ${resp.valid} matches expected` }\n : { ok: false, detail: `verify returned ${resp.valid}, expected ${v.expected}` };\n }\n }\n}\n"]}
{"version":3,"file":"kat.js","sourceRoot":"","sources":["../../src/categories/kat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * KAT category — Known-Answer Tests against OFFICIAL NIST ACVP vectors.\n *\n * This category is SKIPPED unless the user supplies `--vectors <dir>` with real\n * ACVP files. Sieve never fabricates expected values; if no vectors are\n * present, every check is a `skip` with a clear message pointing at\n * vectors/README.md.\n *\n * What we check when vectors ARE present:\n * - kem-keygen: if a seed is given, deterministic keygen must reproduce the\n * expected pk/sk exactly. (Skipped if the SUT can't do seeded keygen.)\n * - kem-encap: if coins are given, deterministic encaps must reproduce ct/ss.\n * - kem-decap: decaps(sk, ct) must equal the expected ss exactly.\n * - dsa-verify: verify(pk, msg, sig) must equal the expected verdict.\n *\n * These ARE exact-value assertions — but the expected bytes come from the\n * user's NIST files, not from Sieve.\n */\n\nimport {\n type Category,\n type CategoryResult,\n type Check,\n fail,\n pass,\n rollUp,\n skip,\n} from \"./types.js\";\nimport { bytesEqual } from \"./helpers.js\";\nimport { fromB64, toB64 } from \"../protocol.js\";\nimport { loadVectors, type Vector } from \"../vectors.js\";\n\nexport const kat: Category = async (ctx): Promise<CategoryResult> => {\n if (!ctx.vectorsDir) {\n return {\n category: \"kat\",\n status: \"skip\",\n checks: [\n skip(\n \"vectors\",\n \"no --vectors <dir> supplied; Sieve ships no test vectors and will not \" +\n \"fabricate them. See vectors/README.md to obtain official NIST ACVP files.\",\n ),\n ],\n summary: \"skipped — no official vectors provided\",\n };\n }\n\n const checks: Check[] = [];\n let loaded: ReturnType<typeof loadVectors>;\n try {\n loaded = loadVectors(ctx.vectorsDir);\n } catch (err) {\n return {\n category: \"kat\",\n status: \"fail\",\n checks: [\n fail(\"load\", `could not load vectors from ${ctx.vectorsDir}: ${(err as Error).message}`),\n ],\n summary: \"vector load failed\",\n };\n }\n\n for (const note of loaded.notes.slice(0, 10)) {\n checks.push(skip(\"note\", note));\n }\n\n // Only run vectors matching the parameter set under test.\n const param = ctx.sizes.id;\n const relevant = loaded.vectors.filter((v) => v.param === param);\n if (relevant.length === 0) {\n checks.push(\n skip(\n \"applicable\",\n `loaded ${loaded.vectors.length} vector(s) from ${loaded.files.length} file(s), ` +\n `but none for ${param}`,\n ),\n );\n const status = rollUp(checks);\n return { category: \"kat\", status, checks, summary: `no ${param} vectors among supplied files` };\n }\n\n let okCount = 0;\n let skipCount = 0;\n let idx = 0;\n for (const v of relevant) {\n idx++;\n try {\n const result = await checkVector(ctx, v);\n if (result.skipped) {\n // Unverifiable (e.g. a keygen vector with no seed) — NOT a match. Record it as\n // a skip so it can't inflate the \"matched\" count into a false conformance pass.\n skipCount++;\n checks.push(skip(`${v.kind}[${idx}]`, result.detail));\n } else if (result.ok) {\n okCount++;\n // Keep the report compact: don't push a pass per vector.\n } else {\n checks.push(fail(`${v.kind}[${idx}]`, result.detail, undefined));\n }\n } catch (err) {\n checks.push(fail(`${v.kind}[${idx}]`, `harness error: ${(err as Error).message}`));\n }\n }\n\n // Denominator is the number of ACTUALLY-verified vectors, excluding skips.\n const verified = relevant.length - skipCount;\n if (okCount > 0) {\n checks.push(pass(\"kat\", `${okCount}/${verified} ${param} vectors matched expected values`));\n } else if (skipCount > 0) {\n // Everything relevant was unverifiable — say so explicitly rather than passing on\n // zero comparisons.\n checks.push(\n skip(\"kat\", `all ${skipCount} ${param} vector(s) were unverifiable (no seed/coins)`),\n );\n }\n\n const status = rollUp(checks);\n return {\n category: \"kat\",\n status,\n checks,\n summary:\n status === \"pass\"\n ? `${okCount} ${param} KAT vectors passed`\n : `${checks.filter((c) => c.status === \"fail\").length} KAT mismatch(es)`,\n };\n};\n\ninterface VectorResult {\n ok: boolean;\n /** True when the vector could not be verified (no seed/coins) — NOT a match. */\n skipped?: boolean;\n detail: string;\n}\n\nasync function checkVector(\n ctx: import(\"./types.js\").CategoryContext,\n v: Vector,\n): Promise<VectorResult> {\n const { runner } = ctx;\n const param = v.param;\n\n switch (v.kind) {\n case \"kem-keygen\": {\n if (!v.seed) return { ok: false, skipped: true, detail: \"no seed; skipped\" };\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"keygen\",\n seed: toB64(v.seed),\n });\n if (resp.ok !== true || !(\"pk\" in resp) || !(\"sk\" in resp)) {\n return {\n ok: false,\n detail: \"seeded keygen did not return pk/sk (SUT may not support seeds)\",\n };\n }\n const pkOk = bytesEqual(fromB64(resp.pk), v.pk);\n const skOk = bytesEqual(fromB64(resp.sk), v.sk);\n return pkOk && skOk\n ? { ok: true, detail: \"pk/sk match\" }\n : { ok: false, detail: `seeded keygen mismatch (pkOk=${pkOk}, skOk=${skOk})` };\n }\n case \"kem-encap\": {\n if (!v.coins) return { ok: false, skipped: true, detail: \"no coins; skipped\" };\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"encaps\",\n pk: toB64(v.pk),\n coins: toB64(v.coins),\n });\n if (resp.ok !== true || !(\"ct\" in resp) || !(\"ss\" in resp)) {\n return {\n ok: false,\n detail: \"deterministic encaps did not return ct/ss (SUT may not support coins)\",\n };\n }\n const ctOk = bytesEqual(fromB64(resp.ct), v.ct);\n const ssOk = bytesEqual(fromB64(resp.ss), v.ss);\n return ctOk && ssOk\n ? { ok: true, detail: \"ct/ss match\" }\n : { ok: false, detail: `encaps mismatch (ctOk=${ctOk}, ssOk=${ssOk})` };\n }\n case \"kem-decap\": {\n const resp = await runner.send({\n family: \"ml-kem\",\n param,\n op: \"decaps\",\n sk: toB64(v.sk),\n ct: toB64(v.ct),\n });\n if (resp.ok !== true || !(\"ss\" in resp)) {\n return { ok: false, detail: \"decaps did not return ss\" };\n }\n return bytesEqual(fromB64(resp.ss), v.ss)\n ? { ok: true, detail: \"ss matches\" }\n : { ok: false, detail: \"decaps shared secret does not match expected\" };\n }\n case \"dsa-verify\": {\n const resp = await runner.send({\n family: \"ml-dsa\",\n param,\n op: \"verify\",\n pk: toB64(v.pk),\n msg: toB64(v.msg),\n sig: toB64(v.sig),\n });\n if (resp.ok !== true || !(\"valid\" in resp)) {\n return { ok: false, detail: \"verify did not return a 'valid' verdict\" };\n }\n return resp.valid === v.expected\n ? { ok: true, detail: `verdict ${resp.valid} matches expected` }\n : { ok: false, detail: `verify returned ${resp.valid}, expected ${v.expected}` };\n }\n }\n}\n"]}

@@ -17,3 +17,3 @@ /**

/** Operation names, shared across families where the semantics overlap. */
export type Op = "keygen" | "encaps" | "decaps" | "sign" | "verify";
type Op = "keygen" | "encaps" | "decaps" | "sign" | "verify";
/** Families that support the signature operations (sign / verify). */

@@ -33,3 +33,3 @@ export type SignatureFamily = "ml-dsa" | "slh-dsa";

/** ML-KEM / ML-DSA key generation. `seed` (base64) makes it deterministic. */
export interface KeygenRequest extends RequestBase {
interface KeygenRequest extends RequestBase {
op: "keygen";

@@ -40,3 +40,3 @@ /** Optional base64 seed for deterministic keygen (impl-defined length). */

/** ML-KEM encapsulation against a public key. */
export interface EncapsRequest extends RequestBase {
interface EncapsRequest extends RequestBase {
family: "ml-kem";

@@ -50,3 +50,3 @@ op: "encaps";

/** ML-KEM decapsulation of a ciphertext with a secret key. */
export interface DecapsRequest extends RequestBase {
interface DecapsRequest extends RequestBase {
family: "ml-kem";

@@ -60,3 +60,3 @@ op: "decaps";

/** ML-DSA / SLH-DSA signature generation. */
export interface SignRequest extends RequestBase {
interface SignRequest extends RequestBase {
family: SignatureFamily;

@@ -70,3 +70,3 @@ op: "sign";

/** ML-DSA / SLH-DSA signature verification. */
export interface VerifyRequest extends RequestBase {
interface VerifyRequest extends RequestBase {
family: SignatureFamily;

@@ -93,3 +93,3 @@ op: "verify";

/** Successful keygen result. */
export interface KeygenResult {
interface KeygenResult {
id: number;

@@ -103,3 +103,3 @@ ok: true;

/** Successful encapsulation result. */
export interface EncapsResult {
interface EncapsResult {
id: number;

@@ -113,3 +113,3 @@ ok: true;

/** Successful decapsulation result. */
export interface DecapsResult {
interface DecapsResult {
id: number;

@@ -121,3 +121,3 @@ ok: true;

/** Successful signing result. */
export interface SignResult {
interface SignResult {
id: number;

@@ -141,3 +141,3 @@ ok: true;

*/
export interface ErrorResult {
interface ErrorResult {
id: number;

@@ -152,4 +152,2 @@ ok: false;

export type Response = KeygenResult | EncapsResult | DecapsResult | SignResult | VerifyResult | ErrorResult;
/** A successful (non-error) response. */
export type SuccessResponse = Exclude<Response, ErrorResult>;
/** Serialize a request to a single NDJSON line (including the trailing "\n"). */

@@ -156,0 +154,0 @@ export declare function encodeRequest(req: Request): string;

@@ -1,1 +0,1 @@

{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Sieve <-> SUT wire protocol.\n *\n * Sieve drives a system-under-test (SUT) — any ML-KEM / ML-DSA implementation\n * the user provides — by spawning it as a child process and exchanging\n * newline-delimited JSON (NDJSON) over stdin/stdout. One request per line, one\n * response per line. All byte fields are base64-encoded strings.\n *\n * This module defines the request/response TypeScript types and the\n * (de)serialization + validation logic. It performs NO cryptography. See\n * PROTOCOL.md for the human-readable specification.\n */\n\nimport type { Family, ParamSet } from \"./sizes.js\";\n\n/** Protocol version. Bumped on any breaking wire change. */\nexport const PROTOCOL_VERSION = 1 as const;\n\n// ---------------------------------------------------------------------------\n// Request types\n// ---------------------------------------------------------------------------\n\n/** Operation names, shared across families where the semantics overlap. */\nexport type Op = \"keygen\" | \"encaps\" | \"decaps\" | \"sign\" | \"verify\";\n\n/** Families that support the signature operations (sign / verify). */\nexport type SignatureFamily = \"ml-dsa\" | \"slh-dsa\";\n\n/** Fields common to every request. */\ninterface RequestBase {\n /** Correlation id; the SUT MUST echo it back on the matching response. */\n id: number;\n /** Algorithm family this request targets. */\n family: Family;\n /** Parameter-set identifier, e.g. \"ml-kem-768\". */\n param: ParamSet;\n /** Operation to perform. */\n op: Op;\n}\n\n/** ML-KEM / ML-DSA key generation. `seed` (base64) makes it deterministic. */\nexport interface KeygenRequest extends RequestBase {\n op: \"keygen\";\n /** Optional base64 seed for deterministic keygen (impl-defined length). */\n seed?: string;\n}\n\n/** ML-KEM encapsulation against a public key. */\nexport interface EncapsRequest extends RequestBase {\n family: \"ml-kem\";\n op: \"encaps\";\n /** Base64 public (encapsulation) key. */\n pk: string;\n /** Optional base64 coins/randomness for deterministic encapsulation. */\n coins?: string;\n}\n\n/** ML-KEM decapsulation of a ciphertext with a secret key. */\nexport interface DecapsRequest extends RequestBase {\n family: \"ml-kem\";\n op: \"decaps\";\n /** Base64 secret (decapsulation) key. */\n sk: string;\n /** Base64 ciphertext. */\n ct: string;\n}\n\n/** ML-DSA / SLH-DSA signature generation. */\nexport interface SignRequest extends RequestBase {\n family: SignatureFamily;\n op: \"sign\";\n /** Base64 secret (signing) key. */\n sk: string;\n /** Base64 message to sign. */\n msg: string;\n}\n\n/** ML-DSA / SLH-DSA signature verification. */\nexport interface VerifyRequest extends RequestBase {\n family: SignatureFamily;\n op: \"verify\";\n /** Base64 public (verification) key. */\n pk: string;\n /** Base64 message. */\n msg: string;\n /** Base64 signature. */\n sig: string;\n}\n\n/** Any request Sieve may send. */\nexport type Request = KeygenRequest | EncapsRequest | DecapsRequest | SignRequest | VerifyRequest;\n\n/**\n * Omit that distributes over a union, so each variant keeps its own fields\n * (plain `Omit<Request, \"id\">` would collapse to only the common keys).\n */\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\n\n/** A request as handed to the runner — the `id` is assigned by the runner. */\nexport type RequestInput = DistributiveOmit<Request, \"id\"> & { id?: number };\n\n// ---------------------------------------------------------------------------\n// Response types\n// ---------------------------------------------------------------------------\n\n/** Successful keygen result. */\nexport interface KeygenResult {\n id: number;\n ok: true;\n /** Base64 public key. */\n pk: string;\n /** Base64 secret key. */\n sk: string;\n}\n\n/** Successful encapsulation result. */\nexport interface EncapsResult {\n id: number;\n ok: true;\n /** Base64 ciphertext. */\n ct: string;\n /** Base64 shared secret. */\n ss: string;\n}\n\n/** Successful decapsulation result. */\nexport interface DecapsResult {\n id: number;\n ok: true;\n /** Base64 shared secret. */\n ss: string;\n}\n\n/** Successful signing result. */\nexport interface SignResult {\n id: number;\n ok: true;\n /** Base64 signature. */\n sig: string;\n}\n\n/** Successful verification result. `valid` is the verification verdict. */\nexport interface VerifyResult {\n id: number;\n ok: true;\n /** Whether the signature verified against (pk, msg). */\n valid: boolean;\n}\n\n/**\n * A defined, well-formed error. The SUT MUST return this (not crash, not hang,\n * not silently produce garbage) when it cannot or will not honor a request —\n * for example when given a wrong-length key. Sieve treats a clean `error`\n * response as a *correct* rejection in the size/robustness categories.\n */\nexport interface ErrorResult {\n id: number;\n ok: false;\n /** Short machine-readable code, e.g. \"invalid-length\", \"unsupported\". */\n code: string;\n /** Human-readable detail. */\n message: string;\n}\n\n/** Any response the SUT may emit. */\nexport type Response =\n | KeygenResult\n | EncapsResult\n | DecapsResult\n | SignResult\n | VerifyResult\n | ErrorResult;\n\n/** A successful (non-error) response. */\nexport type SuccessResponse = Exclude<Response, ErrorResult>;\n\n// ---------------------------------------------------------------------------\n// Serialization\n// ---------------------------------------------------------------------------\n\n/** Serialize a request to a single NDJSON line (including the trailing \"\\n\"). */\nexport function encodeRequest(req: Request): string {\n return JSON.stringify(req) + \"\\n\";\n}\n\n/** Raised when a line from the SUT cannot be parsed into a valid Response. */\nexport class ProtocolError extends Error {\n /** The offending raw line, truncated for safety. */\n readonly raw: string;\n constructor(message: string, raw: string) {\n super(message);\n this.name = \"ProtocolError\";\n this.raw = raw.length > 512 ? raw.slice(0, 512) + \"…\" : raw;\n }\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isStr(v: unknown): v is string {\n return typeof v === \"string\";\n}\n\n/**\n * Parse one NDJSON line from the SUT into a validated {@link Response}.\n *\n * Validates structural shape only (presence and types of fields); it does NOT\n * validate cryptographic content or byte lengths — that is the categories'\n * job. Throws {@link ProtocolError} on malformed input.\n */\nexport function decodeResponse(line: string): Response {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n throw new ProtocolError(\"empty line\", line);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch (err) {\n throw new ProtocolError(`not valid JSON: ${(err as Error).message}`, line);\n }\n\n if (!isObject(parsed)) {\n throw new ProtocolError(\"response is not a JSON object\", line);\n }\n\n const id = parsed[\"id\"];\n if (typeof id !== \"number\" || !Number.isInteger(id)) {\n throw new ProtocolError(\"missing/invalid integer 'id'\", line);\n }\n\n const ok = parsed[\"ok\"];\n if (typeof ok !== \"boolean\") {\n throw new ProtocolError(\"missing/invalid boolean 'ok'\", line);\n }\n\n if (ok === false) {\n const code = parsed[\"code\"];\n const message = parsed[\"message\"];\n if (!isStr(code) || !isStr(message)) {\n throw new ProtocolError(\"error response must have string 'code' and 'message'\", line);\n }\n return { id, ok: false, code, message };\n }\n\n // ok === true: discriminate by which payload fields are present.\n if (isStr(parsed[\"pk\"]) && isStr(parsed[\"sk\"])) {\n return { id, ok: true, pk: parsed[\"pk\"], sk: parsed[\"sk\"] };\n }\n if (isStr(parsed[\"ct\"]) && isStr(parsed[\"ss\"])) {\n return { id, ok: true, ct: parsed[\"ct\"], ss: parsed[\"ss\"] };\n }\n if (isStr(parsed[\"ss\"])) {\n return { id, ok: true, ss: parsed[\"ss\"] };\n }\n if (isStr(parsed[\"sig\"])) {\n return { id, ok: true, sig: parsed[\"sig\"] };\n }\n if (typeof parsed[\"valid\"] === \"boolean\") {\n return { id, ok: true, valid: parsed[\"valid\"] };\n }\n\n throw new ProtocolError(\n \"ok response has no recognizable payload \" + \"(expected pk+sk, ct+ss, ss, sig, or valid)\",\n line,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Base64 helpers (Node built-in Buffer — no external dependency)\n// ---------------------------------------------------------------------------\n\n/** Encode raw bytes to a base64 string. */\nexport function toB64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"base64\");\n}\n\n/**\n * Decode a base64 string to bytes.\n *\n * @throws {ProtocolError} if the input is not valid base64 (i.e. re-encoding\n * the decoded bytes does not reproduce the canonical form).\n */\nexport function fromB64(b64: string): Uint8Array {\n const buf = Buffer.from(b64, \"base64\");\n // Buffer.from is lenient; sanity-check by re-encoding the canonical form.\n if (buf.toString(\"base64\").replace(/=+$/, \"\") !== b64.replace(/\\s/g, \"\").replace(/=+$/, \"\")) {\n throw new ProtocolError(\"invalid base64\", b64);\n }\n return new Uint8Array(buf);\n}\n"]}
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Sieve <-> SUT wire protocol.\n *\n * Sieve drives a system-under-test (SUT) — any ML-KEM / ML-DSA implementation\n * the user provides — by spawning it as a child process and exchanging\n * newline-delimited JSON (NDJSON) over stdin/stdout. One request per line, one\n * response per line. All byte fields are base64-encoded strings.\n *\n * This module defines the request/response TypeScript types and the\n * (de)serialization + validation logic. It performs NO cryptography. See\n * PROTOCOL.md for the human-readable specification.\n */\n\nimport type { Family, ParamSet } from \"./sizes.js\";\n\n/** Protocol version. Bumped on any breaking wire change. */\nexport const PROTOCOL_VERSION = 1 as const;\n\n// ---------------------------------------------------------------------------\n// Request types\n// ---------------------------------------------------------------------------\n\n/** Operation names, shared across families where the semantics overlap. */\ntype Op = \"keygen\" | \"encaps\" | \"decaps\" | \"sign\" | \"verify\";\n\n/** Families that support the signature operations (sign / verify). */\nexport type SignatureFamily = \"ml-dsa\" | \"slh-dsa\";\n\n/** Fields common to every request. */\ninterface RequestBase {\n /** Correlation id; the SUT MUST echo it back on the matching response. */\n id: number;\n /** Algorithm family this request targets. */\n family: Family;\n /** Parameter-set identifier, e.g. \"ml-kem-768\". */\n param: ParamSet;\n /** Operation to perform. */\n op: Op;\n}\n\n/** ML-KEM / ML-DSA key generation. `seed` (base64) makes it deterministic. */\ninterface KeygenRequest extends RequestBase {\n op: \"keygen\";\n /** Optional base64 seed for deterministic keygen (impl-defined length). */\n seed?: string;\n}\n\n/** ML-KEM encapsulation against a public key. */\ninterface EncapsRequest extends RequestBase {\n family: \"ml-kem\";\n op: \"encaps\";\n /** Base64 public (encapsulation) key. */\n pk: string;\n /** Optional base64 coins/randomness for deterministic encapsulation. */\n coins?: string;\n}\n\n/** ML-KEM decapsulation of a ciphertext with a secret key. */\ninterface DecapsRequest extends RequestBase {\n family: \"ml-kem\";\n op: \"decaps\";\n /** Base64 secret (decapsulation) key. */\n sk: string;\n /** Base64 ciphertext. */\n ct: string;\n}\n\n/** ML-DSA / SLH-DSA signature generation. */\ninterface SignRequest extends RequestBase {\n family: SignatureFamily;\n op: \"sign\";\n /** Base64 secret (signing) key. */\n sk: string;\n /** Base64 message to sign. */\n msg: string;\n}\n\n/** ML-DSA / SLH-DSA signature verification. */\ninterface VerifyRequest extends RequestBase {\n family: SignatureFamily;\n op: \"verify\";\n /** Base64 public (verification) key. */\n pk: string;\n /** Base64 message. */\n msg: string;\n /** Base64 signature. */\n sig: string;\n}\n\n/** Any request Sieve may send. */\nexport type Request = KeygenRequest | EncapsRequest | DecapsRequest | SignRequest | VerifyRequest;\n\n/**\n * Omit that distributes over a union, so each variant keeps its own fields\n * (plain `Omit<Request, \"id\">` would collapse to only the common keys).\n */\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\n\n/** A request as handed to the runner — the `id` is assigned by the runner. */\nexport type RequestInput = DistributiveOmit<Request, \"id\"> & { id?: number };\n\n// ---------------------------------------------------------------------------\n// Response types\n// ---------------------------------------------------------------------------\n\n/** Successful keygen result. */\ninterface KeygenResult {\n id: number;\n ok: true;\n /** Base64 public key. */\n pk: string;\n /** Base64 secret key. */\n sk: string;\n}\n\n/** Successful encapsulation result. */\ninterface EncapsResult {\n id: number;\n ok: true;\n /** Base64 ciphertext. */\n ct: string;\n /** Base64 shared secret. */\n ss: string;\n}\n\n/** Successful decapsulation result. */\ninterface DecapsResult {\n id: number;\n ok: true;\n /** Base64 shared secret. */\n ss: string;\n}\n\n/** Successful signing result. */\ninterface SignResult {\n id: number;\n ok: true;\n /** Base64 signature. */\n sig: string;\n}\n\n/** Successful verification result. `valid` is the verification verdict. */\nexport interface VerifyResult {\n id: number;\n ok: true;\n /** Whether the signature verified against (pk, msg). */\n valid: boolean;\n}\n\n/**\n * A defined, well-formed error. The SUT MUST return this (not crash, not hang,\n * not silently produce garbage) when it cannot or will not honor a request —\n * for example when given a wrong-length key. Sieve treats a clean `error`\n * response as a *correct* rejection in the size/robustness categories.\n */\ninterface ErrorResult {\n id: number;\n ok: false;\n /** Short machine-readable code, e.g. \"invalid-length\", \"unsupported\". */\n code: string;\n /** Human-readable detail. */\n message: string;\n}\n\n/** Any response the SUT may emit. */\nexport type Response =\n | KeygenResult\n | EncapsResult\n | DecapsResult\n | SignResult\n | VerifyResult\n | ErrorResult;\n\n// ---------------------------------------------------------------------------\n// Serialization\n// ---------------------------------------------------------------------------\n\n/** Serialize a request to a single NDJSON line (including the trailing \"\\n\"). */\nexport function encodeRequest(req: Request): string {\n return JSON.stringify(req) + \"\\n\";\n}\n\n/** Raised when a line from the SUT cannot be parsed into a valid Response. */\nexport class ProtocolError extends Error {\n /** The offending raw line, truncated for safety. */\n readonly raw: string;\n constructor(message: string, raw: string) {\n super(message);\n this.name = \"ProtocolError\";\n this.raw = raw.length > 512 ? raw.slice(0, 512) + \"…\" : raw;\n }\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isStr(v: unknown): v is string {\n return typeof v === \"string\";\n}\n\n/**\n * Parse one NDJSON line from the SUT into a validated {@link Response}.\n *\n * Validates structural shape only (presence and types of fields); it does NOT\n * validate cryptographic content or byte lengths — that is the categories'\n * job. Throws {@link ProtocolError} on malformed input.\n */\nexport function decodeResponse(line: string): Response {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n throw new ProtocolError(\"empty line\", line);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch (err) {\n throw new ProtocolError(`not valid JSON: ${(err as Error).message}`, line);\n }\n\n if (!isObject(parsed)) {\n throw new ProtocolError(\"response is not a JSON object\", line);\n }\n\n const id = parsed[\"id\"];\n if (typeof id !== \"number\" || !Number.isInteger(id)) {\n throw new ProtocolError(\"missing/invalid integer 'id'\", line);\n }\n\n const ok = parsed[\"ok\"];\n if (typeof ok !== \"boolean\") {\n throw new ProtocolError(\"missing/invalid boolean 'ok'\", line);\n }\n\n if (ok === false) {\n const code = parsed[\"code\"];\n const message = parsed[\"message\"];\n if (!isStr(code) || !isStr(message)) {\n throw new ProtocolError(\"error response must have string 'code' and 'message'\", line);\n }\n return { id, ok: false, code, message };\n }\n\n // ok === true: discriminate by which payload fields are present.\n if (isStr(parsed[\"pk\"]) && isStr(parsed[\"sk\"])) {\n return { id, ok: true, pk: parsed[\"pk\"], sk: parsed[\"sk\"] };\n }\n if (isStr(parsed[\"ct\"]) && isStr(parsed[\"ss\"])) {\n return { id, ok: true, ct: parsed[\"ct\"], ss: parsed[\"ss\"] };\n }\n if (isStr(parsed[\"ss\"])) {\n return { id, ok: true, ss: parsed[\"ss\"] };\n }\n if (isStr(parsed[\"sig\"])) {\n return { id, ok: true, sig: parsed[\"sig\"] };\n }\n if (typeof parsed[\"valid\"] === \"boolean\") {\n return { id, ok: true, valid: parsed[\"valid\"] };\n }\n\n throw new ProtocolError(\n \"ok response has no recognizable payload \" + \"(expected pk+sk, ct+ss, ss, sig, or valid)\",\n line,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Base64 helpers (Node built-in Buffer — no external dependency)\n// ---------------------------------------------------------------------------\n\n/** Encode raw bytes to a base64 string. */\nexport function toB64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"base64\");\n}\n\n/**\n * Decode a base64 string to bytes.\n *\n * @throws {ProtocolError} if the input is not valid base64 (i.e. re-encoding\n * the decoded bytes does not reproduce the canonical form).\n */\nexport function fromB64(b64: string): Uint8Array {\n const buf = Buffer.from(b64, \"base64\");\n // Buffer.from is lenient; sanity-check by re-encoding the canonical form.\n if (buf.toString(\"base64\").replace(/=+$/, \"\") !== b64.replace(/\\s/g, \"\").replace(/=+$/, \"\")) {\n throw new ProtocolError(\"invalid base64\", b64);\n }\n return new Uint8Array(buf);\n}\n"]}

@@ -18,3 +18,3 @@ /**

/** A normalized ML-KEM keygen vector: seed -> (pk, sk). */
export interface KemKeygenVector {
interface KemKeygenVector {
kind: "kem-keygen";

@@ -28,3 +28,3 @@ param: ParamSet;

/** A normalized ML-KEM encapsulation vector: (pk, coins) -> (ct, ss). */
export interface KemEncapVector {
interface KemEncapVector {
kind: "kem-encap";

@@ -39,3 +39,3 @@ param: ParamSet;

/** A normalized ML-KEM decapsulation vector: (sk, ct) -> ss. */
export interface KemDecapVector {
interface KemDecapVector {
kind: "kem-decap";

@@ -48,3 +48,3 @@ param: ParamSet;

/** A normalized ML-DSA signature-verification vector: (pk, msg, sig) -> ok. */
export interface DsaVerifyVector {
interface DsaVerifyVector {
kind: "dsa-verify";

@@ -91,2 +91,3 @@ param: ParamSet;

export declare function loadVectors(dir: string): VectorSet;
export {};
//# sourceMappingURL=vectors.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"vectors.d.ts","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAU,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,QAAQ,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,6BAA6B;AAC7B,MAAM,MAAM,MAAM,GAAG,eAAe,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8CAA8C;AAC9C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yDAAyD;IACzD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,4EAA4E;IAC5E,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AA6JD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAsElD"}
{"version":3,"file":"vectors.d.ts","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAU,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,2DAA2D;AAC3D,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,QAAQ,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,yEAAyE;AACzE,UAAU,cAAc;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,gEAAgE;AAChE,UAAU,cAAc;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;IACf,EAAE,EAAE,UAAU,CAAC;CAChB;AAED,+EAA+E;AAC/E,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,6BAA6B;AAC7B,MAAM,MAAM,MAAM,GAAG,eAAe,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8CAA8C;AAC9C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yDAAyD;IACzD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,4EAA4E;IAC5E,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AA6JD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAsElD"}

@@ -1,1 +0,1 @@

{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loader for OFFICIAL NIST ACVP Known-Answer-Test (KAT) vector files.\n *\n * HONESTY NOTE: Sieve ships NO cryptographic test vectors. It does not and must\n * not fabricate expected pk/sk/ct/ss/sig bytes. This module only PARSES vector\n * files that the user downloads from NIST and points Sieve at via --vectors.\n * See vectors/README.md for where to obtain them and the file format.\n *\n * Supported input: the NIST ACVP-server JSON format for ML-KEM (keyGen,\n * encapDecap) and ML-DSA (keyGen, sigGen, sigVer). The ACVP JSON encodes bytes\n * as hex strings. We normalize the fields we need into a flat list of typed\n * test cases. Anything we don't recognize is ignored (not invented).\n *\n * Uses only node:fs. No cryptography.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { isParamSet } from \"./sizes.js\";\nimport type { Family, ParamSet } from \"./sizes.js\";\n\n/** A normalized ML-KEM keygen vector: seed -> (pk, sk). */\nexport interface KemKeygenVector {\n kind: \"kem-keygen\";\n param: ParamSet;\n /** Concatenated d||z seed (hex-decoded). */\n seed?: Uint8Array;\n pk: Uint8Array;\n sk: Uint8Array;\n}\n\n/** A normalized ML-KEM encapsulation vector: (pk, coins) -> (ct, ss). */\nexport interface KemEncapVector {\n kind: \"kem-encap\";\n param: ParamSet;\n pk: Uint8Array;\n /** Encapsulation coins/message m (hex-decoded), if present. */\n coins?: Uint8Array;\n ct: Uint8Array;\n ss: Uint8Array;\n}\n\n/** A normalized ML-KEM decapsulation vector: (sk, ct) -> ss. */\nexport interface KemDecapVector {\n kind: \"kem-decap\";\n param: ParamSet;\n sk: Uint8Array;\n ct: Uint8Array;\n ss: Uint8Array;\n}\n\n/** A normalized ML-DSA signature-verification vector: (pk, msg, sig) -> ok. */\nexport interface DsaVerifyVector {\n kind: \"dsa-verify\";\n param: ParamSet;\n pk: Uint8Array;\n msg: Uint8Array;\n sig: Uint8Array;\n expected: boolean;\n}\n\n/** Any normalized vector. */\nexport type Vector = KemKeygenVector | KemEncapVector | KemDecapVector | DsaVerifyVector;\n\n/**\n * Provenance of one ACVP vector file (docs/compliance/acvp-provenance.md): a\n * content hash over the RAW bytes plus the declared source, so a passing `kat`\n * run is traceable to the exact operator-supplied inputs. Sieve records what it\n * was given; it never fetches or ships vectors (ADR-0004).\n */\nexport interface VectorFileProvenance {\n path: string;\n sha256: string;\n sizeBytes: number;\n algorithm: string | null;\n mode: string | null;\n /** Parameter sets seen in the file. */\n parameterSets: string[];\n /** Operator-declared origin, or \"unknown (operator-supplied)\". */\n sourceUrl: string;\n /** Recognized test cases consumed from this file. */\n casesUsed: number;\n}\n\n/** Result of scanning a vectors directory. */\nexport interface VectorSet {\n vectors: Vector[];\n /** Files that were read. */\n files: string[];\n /** Non-fatal parse notes (unrecognized files/groups). */\n notes: string[];\n /** Per-file provenance for every vector file used (kat traceability). */\n provenance: VectorFileProvenance[];\n /** True when the operator declared a source via `vectors-manifest.json`. */\n provenanceDeclared: boolean;\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const clean = hex.trim();\n if (clean.length === 0) return new Uint8Array(0);\n if (clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {\n throw new Error(`invalid hex string (len ${clean.length})`);\n }\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\n/** Map an ACVP parameterSet string to our canonical ParamSet, or undefined.\n * ACVP uses e.g. \"ML-KEM-768\", \"ML-DSA-65\", \"SLH-DSA-SHA2-128s\" — lower-casing\n * and `_`→`-` yields our canonical ids for all three families (incl. FIPS 205). */\nfunction normParam(family: Family, raw: unknown): ParamSet | undefined {\n if (typeof raw !== \"string\") return undefined;\n const s = raw.toLowerCase().replace(/_/g, \"-\");\n if (isParamSet(s) && s.startsWith(family)) return s;\n return undefined;\n}\n\nfunction asArray(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\nfunction asObj(v: unknown): Record<string, unknown> {\n return typeof v === \"object\" && v !== null ? (v as Record<string, unknown>) : {};\n}\nfunction str(v: unknown): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/**\n * Parse one ACVP test-vectors JSON document into normalized vectors.\n * The ACVP shape is: { algorithm, mode, testGroups: [{ parameterSet, tests:[...] }] }.\n */\nfunction parseAcvpDocument(doc: unknown, notes: string[], file: string): Vector[] {\n const root = asObj(doc);\n const algorithm = str(root[\"algorithm\"])?.toUpperCase() ?? \"\";\n const mode = str(root[\"mode\"])?.toLowerCase() ?? \"\";\n const out: Vector[] = [];\n\n // Order matters: \"SLH-DSA\" contains \"DSA\", so test SLH before the ML-DSA branch.\n const family: Family | undefined = algorithm.includes(\"KEM\")\n ? \"ml-kem\"\n : algorithm.includes(\"SLH\")\n ? \"slh-dsa\"\n : algorithm.includes(\"DSA\")\n ? \"ml-dsa\"\n : undefined;\n if (family === undefined) {\n notes.push(`${file}: unrecognized algorithm \"${algorithm}\", skipped`);\n return out;\n }\n\n for (const groupRaw of asArray(root[\"testGroups\"])) {\n const group = asObj(groupRaw);\n const param = normParam(family, group[\"parameterSet\"]);\n if (param === undefined) {\n notes.push(`${file}: skipped group with parameterSet=${String(group[\"parameterSet\"])}`);\n continue;\n }\n const fn = str(group[\"function\"])?.toLowerCase(); // encapDecap: \"encapsulation\"/\"decapsulation\"\n\n for (const testRaw of asArray(group[\"tests\"])) {\n const t = asObj(testRaw);\n try {\n if (family === \"ml-kem\") {\n if (mode.includes(\"keygen\")) {\n const d = str(t[\"d\"]);\n const z = str(t[\"z\"]);\n const seedHex = str(t[\"seed\"]) ?? (d && z ? d + z : undefined);\n out.push({\n kind: \"kem-keygen\",\n param,\n ...(seedHex ? { seed: hexToBytes(seedHex) } : {}),\n pk: hexToBytes(reqHex(t, \"ek\", \"pk\")),\n sk: hexToBytes(reqHex(t, \"dk\", \"sk\")),\n });\n } else if (mode.includes(\"encapdecap\") || mode.includes(\"encap\")) {\n // function may distinguish encapsulation vs decapsulation cases.\n if (fn === \"decapsulation\" || (\"dk\" in t && \"c\" in t)) {\n out.push({\n kind: \"kem-decap\",\n param,\n sk: hexToBytes(reqHex(t, \"dk\", \"sk\")),\n ct: hexToBytes(reqHex(t, \"c\", \"ct\")),\n ss: hexToBytes(reqHex(t, \"k\", \"ss\")),\n });\n } else {\n const m = str(t[\"m\"]);\n out.push({\n kind: \"kem-encap\",\n param,\n pk: hexToBytes(reqHex(t, \"ek\", \"pk\")),\n ...(m ? { coins: hexToBytes(m) } : {}),\n ct: hexToBytes(reqHex(t, \"c\", \"ct\")),\n ss: hexToBytes(reqHex(t, \"k\", \"ss\")),\n });\n }\n } else {\n notes.push(`${file}: unrecognized ML-KEM mode \"${mode}\"`);\n }\n } else {\n // ML-DSA / SLH-DSA: we can robustly check sigVer cases (verdict-driven).\n if (mode.includes(\"sigver\") || (\"signature\" in t && \"pk\" in t)) {\n const expected = t[\"testPassed\"];\n // NIST ACVP sigVer files mix valid and INTENTIONALLY-INVALID\n // signatures; the expected verdict lives in `testPassed`. If that\n // field is absent (or not a boolean) we cannot know whether the\n // signature should verify, so we SKIP the case rather than invent\n // `true` — defaulting to true flags a conformant SUT (which\n // correctly returns valid:false on a bad signature) as failing.\n if (typeof expected !== \"boolean\") {\n notes.push(`${file}: skipped a sigVer case with no boolean \"testPassed\" verdict`);\n continue;\n }\n out.push({\n kind: \"dsa-verify\",\n param,\n pk: hexToBytes(reqHex(t, \"pk\", \"ek\")),\n msg: hexToBytes(reqHex(t, \"message\", \"msg\")),\n sig: hexToBytes(reqHex(t, \"signature\", \"sig\")),\n expected,\n });\n } else {\n notes.push(`${file}: ML-DSA mode \"${mode}\" not used for KAT (sign is nonce-dependent)`);\n }\n }\n } catch (err) {\n notes.push(`${file}: skipped a test case: ${(err as Error).message}`);\n }\n }\n }\n return out;\n}\n\n/** Read the first present hex field among `keys`, else throw. */\nfunction reqHex(t: Record<string, unknown>, ...keys: string[]): string {\n for (const k of keys) {\n const v = str(t[k]);\n if (v !== undefined) return v;\n }\n throw new Error(`missing field (any of: ${keys.join(\", \")})`);\n}\n\n/**\n * Load and normalize all `*.json` ACVP vector files in `dir`.\n *\n * @throws if `dir` does not exist or contains no readable JSON files.\n */\n/** Operator-declared source manifest filename (not itself a vector file). */\nconst VECTORS_MANIFEST = \"vectors-manifest.json\";\n\nexport function loadVectors(dir: string): VectorSet {\n const st = statSync(dir); // throws ENOENT if missing\n if (!st.isDirectory()) {\n throw new Error(`--vectors path is not a directory: ${dir}`);\n }\n\n // Optional provenance manifest: `{ \"sourceUrl\": \"https://…\" }` declaring where\n // the operator obtained these vectors. Absent → provenance is undeclared.\n let declaredSource: string | undefined;\n try {\n const m = JSON.parse(readFileSync(join(dir, VECTORS_MANIFEST), \"utf8\")) as {\n sourceUrl?: unknown;\n };\n if (typeof m.sourceUrl === \"string\" && m.sourceUrl.trim()) declaredSource = m.sourceUrl.trim();\n } catch {\n /* no manifest — provenanceDeclared stays false */\n }\n\n const entries = readdirSync(dir).filter(\n (f) => f.toLowerCase().endsWith(\".json\") && f.toLowerCase() !== VECTORS_MANIFEST,\n );\n if (entries.length === 0) {\n throw new Error(`no .json vector files found in ${dir}`);\n }\n\n const vectors: Vector[] = [];\n const files: string[] = [];\n const notes: string[] = [];\n const provenance: VectorFileProvenance[] = [];\n\n for (const name of entries) {\n const path = join(dir, name);\n // Hash the RAW bytes as supplied, before parsing — proves exactly what was used.\n const raw = readFileSync(path);\n const sha256 = createHash(\"sha256\").update(raw).digest(\"hex\");\n let doc: unknown;\n try {\n doc = JSON.parse(raw.toString(\"utf8\"));\n } catch (err) {\n notes.push(`${name}: not valid JSON (${(err as Error).message})`);\n continue;\n }\n files.push(name);\n const before = vectors.length;\n // ACVP test-vector files may be a single object or an array of prompts.\n const docs = Array.isArray(doc) ? doc : [doc];\n for (const d of docs) {\n vectors.push(...parseAcvpDocument(d, notes, name));\n }\n\n // Best-effort ACVP metadata for the provenance record.\n const root = asObj(docs[0]);\n const params = new Set<string>();\n for (const g of asArray(root[\"testGroups\"])) {\n const p = str(asObj(g)[\"parameterSet\"]);\n if (p) params.add(p);\n }\n provenance.push({\n path: name,\n sha256,\n sizeBytes: raw.length,\n algorithm: str(root[\"algorithm\"]) ?? null,\n mode: str(root[\"mode\"]) ?? null,\n parameterSets: [...params],\n sourceUrl: declaredSource ?? \"unknown (operator-supplied)\",\n casesUsed: vectors.length - before,\n });\n }\n\n return { vectors, files, notes, provenance, provenanceDeclared: declaredSource !== undefined };\n}\n"]}
{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loader for OFFICIAL NIST ACVP Known-Answer-Test (KAT) vector files.\n *\n * HONESTY NOTE: Sieve ships NO cryptographic test vectors. It does not and must\n * not fabricate expected pk/sk/ct/ss/sig bytes. This module only PARSES vector\n * files that the user downloads from NIST and points Sieve at via --vectors.\n * See vectors/README.md for where to obtain them and the file format.\n *\n * Supported input: the NIST ACVP-server JSON format for ML-KEM (keyGen,\n * encapDecap) and ML-DSA (keyGen, sigGen, sigVer). The ACVP JSON encodes bytes\n * as hex strings. We normalize the fields we need into a flat list of typed\n * test cases. Anything we don't recognize is ignored (not invented).\n *\n * Uses only node:fs. No cryptography.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { isParamSet } from \"./sizes.js\";\nimport type { Family, ParamSet } from \"./sizes.js\";\n\n/** A normalized ML-KEM keygen vector: seed -> (pk, sk). */\ninterface KemKeygenVector {\n kind: \"kem-keygen\";\n param: ParamSet;\n /** Concatenated d||z seed (hex-decoded). */\n seed?: Uint8Array;\n pk: Uint8Array;\n sk: Uint8Array;\n}\n\n/** A normalized ML-KEM encapsulation vector: (pk, coins) -> (ct, ss). */\ninterface KemEncapVector {\n kind: \"kem-encap\";\n param: ParamSet;\n pk: Uint8Array;\n /** Encapsulation coins/message m (hex-decoded), if present. */\n coins?: Uint8Array;\n ct: Uint8Array;\n ss: Uint8Array;\n}\n\n/** A normalized ML-KEM decapsulation vector: (sk, ct) -> ss. */\ninterface KemDecapVector {\n kind: \"kem-decap\";\n param: ParamSet;\n sk: Uint8Array;\n ct: Uint8Array;\n ss: Uint8Array;\n}\n\n/** A normalized ML-DSA signature-verification vector: (pk, msg, sig) -> ok. */\ninterface DsaVerifyVector {\n kind: \"dsa-verify\";\n param: ParamSet;\n pk: Uint8Array;\n msg: Uint8Array;\n sig: Uint8Array;\n expected: boolean;\n}\n\n/** Any normalized vector. */\nexport type Vector = KemKeygenVector | KemEncapVector | KemDecapVector | DsaVerifyVector;\n\n/**\n * Provenance of one ACVP vector file (docs/compliance/acvp-provenance.md): a\n * content hash over the RAW bytes plus the declared source, so a passing `kat`\n * run is traceable to the exact operator-supplied inputs. Sieve records what it\n * was given; it never fetches or ships vectors (ADR-0004).\n */\nexport interface VectorFileProvenance {\n path: string;\n sha256: string;\n sizeBytes: number;\n algorithm: string | null;\n mode: string | null;\n /** Parameter sets seen in the file. */\n parameterSets: string[];\n /** Operator-declared origin, or \"unknown (operator-supplied)\". */\n sourceUrl: string;\n /** Recognized test cases consumed from this file. */\n casesUsed: number;\n}\n\n/** Result of scanning a vectors directory. */\nexport interface VectorSet {\n vectors: Vector[];\n /** Files that were read. */\n files: string[];\n /** Non-fatal parse notes (unrecognized files/groups). */\n notes: string[];\n /** Per-file provenance for every vector file used (kat traceability). */\n provenance: VectorFileProvenance[];\n /** True when the operator declared a source via `vectors-manifest.json`. */\n provenanceDeclared: boolean;\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const clean = hex.trim();\n if (clean.length === 0) return new Uint8Array(0);\n if (clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {\n throw new Error(`invalid hex string (len ${clean.length})`);\n }\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\n/** Map an ACVP parameterSet string to our canonical ParamSet, or undefined.\n * ACVP uses e.g. \"ML-KEM-768\", \"ML-DSA-65\", \"SLH-DSA-SHA2-128s\" — lower-casing\n * and `_`→`-` yields our canonical ids for all three families (incl. FIPS 205). */\nfunction normParam(family: Family, raw: unknown): ParamSet | undefined {\n if (typeof raw !== \"string\") return undefined;\n const s = raw.toLowerCase().replace(/_/g, \"-\");\n if (isParamSet(s) && s.startsWith(family)) return s;\n return undefined;\n}\n\nfunction asArray(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\nfunction asObj(v: unknown): Record<string, unknown> {\n return typeof v === \"object\" && v !== null ? (v as Record<string, unknown>) : {};\n}\nfunction str(v: unknown): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/**\n * Parse one ACVP test-vectors JSON document into normalized vectors.\n * The ACVP shape is: { algorithm, mode, testGroups: [{ parameterSet, tests:[...] }] }.\n */\nfunction parseAcvpDocument(doc: unknown, notes: string[], file: string): Vector[] {\n const root = asObj(doc);\n const algorithm = str(root[\"algorithm\"])?.toUpperCase() ?? \"\";\n const mode = str(root[\"mode\"])?.toLowerCase() ?? \"\";\n const out: Vector[] = [];\n\n // Order matters: \"SLH-DSA\" contains \"DSA\", so test SLH before the ML-DSA branch.\n const family: Family | undefined = algorithm.includes(\"KEM\")\n ? \"ml-kem\"\n : algorithm.includes(\"SLH\")\n ? \"slh-dsa\"\n : algorithm.includes(\"DSA\")\n ? \"ml-dsa\"\n : undefined;\n if (family === undefined) {\n notes.push(`${file}: unrecognized algorithm \"${algorithm}\", skipped`);\n return out;\n }\n\n for (const groupRaw of asArray(root[\"testGroups\"])) {\n const group = asObj(groupRaw);\n const param = normParam(family, group[\"parameterSet\"]);\n if (param === undefined) {\n notes.push(`${file}: skipped group with parameterSet=${String(group[\"parameterSet\"])}`);\n continue;\n }\n const fn = str(group[\"function\"])?.toLowerCase(); // encapDecap: \"encapsulation\"/\"decapsulation\"\n\n for (const testRaw of asArray(group[\"tests\"])) {\n const t = asObj(testRaw);\n try {\n if (family === \"ml-kem\") {\n if (mode.includes(\"keygen\")) {\n const d = str(t[\"d\"]);\n const z = str(t[\"z\"]);\n const seedHex = str(t[\"seed\"]) ?? (d && z ? d + z : undefined);\n out.push({\n kind: \"kem-keygen\",\n param,\n ...(seedHex ? { seed: hexToBytes(seedHex) } : {}),\n pk: hexToBytes(reqHex(t, \"ek\", \"pk\")),\n sk: hexToBytes(reqHex(t, \"dk\", \"sk\")),\n });\n } else if (mode.includes(\"encapdecap\") || mode.includes(\"encap\")) {\n // function may distinguish encapsulation vs decapsulation cases.\n if (fn === \"decapsulation\" || (\"dk\" in t && \"c\" in t)) {\n out.push({\n kind: \"kem-decap\",\n param,\n sk: hexToBytes(reqHex(t, \"dk\", \"sk\")),\n ct: hexToBytes(reqHex(t, \"c\", \"ct\")),\n ss: hexToBytes(reqHex(t, \"k\", \"ss\")),\n });\n } else {\n const m = str(t[\"m\"]);\n out.push({\n kind: \"kem-encap\",\n param,\n pk: hexToBytes(reqHex(t, \"ek\", \"pk\")),\n ...(m ? { coins: hexToBytes(m) } : {}),\n ct: hexToBytes(reqHex(t, \"c\", \"ct\")),\n ss: hexToBytes(reqHex(t, \"k\", \"ss\")),\n });\n }\n } else {\n notes.push(`${file}: unrecognized ML-KEM mode \"${mode}\"`);\n }\n } else {\n // ML-DSA / SLH-DSA: we can robustly check sigVer cases (verdict-driven).\n if (mode.includes(\"sigver\") || (\"signature\" in t && \"pk\" in t)) {\n const expected = t[\"testPassed\"];\n // NIST ACVP sigVer files mix valid and INTENTIONALLY-INVALID\n // signatures; the expected verdict lives in `testPassed`. If that\n // field is absent (or not a boolean) we cannot know whether the\n // signature should verify, so we SKIP the case rather than invent\n // `true` — defaulting to true flags a conformant SUT (which\n // correctly returns valid:false on a bad signature) as failing.\n if (typeof expected !== \"boolean\") {\n notes.push(`${file}: skipped a sigVer case with no boolean \"testPassed\" verdict`);\n continue;\n }\n out.push({\n kind: \"dsa-verify\",\n param,\n pk: hexToBytes(reqHex(t, \"pk\", \"ek\")),\n msg: hexToBytes(reqHex(t, \"message\", \"msg\")),\n sig: hexToBytes(reqHex(t, \"signature\", \"sig\")),\n expected,\n });\n } else {\n notes.push(`${file}: ML-DSA mode \"${mode}\" not used for KAT (sign is nonce-dependent)`);\n }\n }\n } catch (err) {\n notes.push(`${file}: skipped a test case: ${(err as Error).message}`);\n }\n }\n }\n return out;\n}\n\n/** Read the first present hex field among `keys`, else throw. */\nfunction reqHex(t: Record<string, unknown>, ...keys: string[]): string {\n for (const k of keys) {\n const v = str(t[k]);\n if (v !== undefined) return v;\n }\n throw new Error(`missing field (any of: ${keys.join(\", \")})`);\n}\n\n/**\n * Load and normalize all `*.json` ACVP vector files in `dir`.\n *\n * @throws if `dir` does not exist or contains no readable JSON files.\n */\n/** Operator-declared source manifest filename (not itself a vector file). */\nconst VECTORS_MANIFEST = \"vectors-manifest.json\";\n\nexport function loadVectors(dir: string): VectorSet {\n const st = statSync(dir); // throws ENOENT if missing\n if (!st.isDirectory()) {\n throw new Error(`--vectors path is not a directory: ${dir}`);\n }\n\n // Optional provenance manifest: `{ \"sourceUrl\": \"https://…\" }` declaring where\n // the operator obtained these vectors. Absent → provenance is undeclared.\n let declaredSource: string | undefined;\n try {\n const m = JSON.parse(readFileSync(join(dir, VECTORS_MANIFEST), \"utf8\")) as {\n sourceUrl?: unknown;\n };\n if (typeof m.sourceUrl === \"string\" && m.sourceUrl.trim()) declaredSource = m.sourceUrl.trim();\n } catch {\n /* no manifest — provenanceDeclared stays false */\n }\n\n const entries = readdirSync(dir).filter(\n (f) => f.toLowerCase().endsWith(\".json\") && f.toLowerCase() !== VECTORS_MANIFEST,\n );\n if (entries.length === 0) {\n throw new Error(`no .json vector files found in ${dir}`);\n }\n\n const vectors: Vector[] = [];\n const files: string[] = [];\n const notes: string[] = [];\n const provenance: VectorFileProvenance[] = [];\n\n for (const name of entries) {\n const path = join(dir, name);\n // Hash the RAW bytes as supplied, before parsing — proves exactly what was used.\n const raw = readFileSync(path);\n const sha256 = createHash(\"sha256\").update(raw).digest(\"hex\");\n let doc: unknown;\n try {\n doc = JSON.parse(raw.toString(\"utf8\"));\n } catch (err) {\n notes.push(`${name}: not valid JSON (${(err as Error).message})`);\n continue;\n }\n files.push(name);\n const before = vectors.length;\n // ACVP test-vector files may be a single object or an array of prompts.\n const docs = Array.isArray(doc) ? doc : [doc];\n for (const d of docs) {\n vectors.push(...parseAcvpDocument(d, notes, name));\n }\n\n // Best-effort ACVP metadata for the provenance record.\n const root = asObj(docs[0]);\n const params = new Set<string>();\n for (const g of asArray(root[\"testGroups\"])) {\n const p = str(asObj(g)[\"parameterSet\"]);\n if (p) params.add(p);\n }\n provenance.push({\n path: name,\n sha256,\n sizeBytes: raw.length,\n algorithm: str(root[\"algorithm\"]) ?? null,\n mode: str(root[\"mode\"]) ?? null,\n parameterSets: [...params],\n sourceUrl: declaredSource ?? \"unknown (operator-supplied)\",\n casesUsed: vectors.length - before,\n });\n }\n\n return { vectors, files, notes, provenance, provenanceDeclared: declaredSource !== undefined };\n}\n"]}
{
"name": "@quantakrypto/sieve",
"version": "0.4.4",
"version": "0.5.0",
"description": "Sieve — conformance battery for ML-KEM / ML-DSA implementations. Drives any implementation over a simple stdin/stdout JSON protocol. Zero runtime dependencies.",

@@ -5,0 +5,0 @@ "license": "Apache-2.0",