@quantakrypto/sieve 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +227 -0
- package/dist/categories/correctness.d.ts +13 -0
- package/dist/categories/correctness.d.ts.map +1 -0
- package/dist/categories/correctness.js +78 -0
- package/dist/categories/correctness.js.map +1 -0
- package/dist/categories/determinism.d.ts +12 -0
- package/dist/categories/determinism.d.ts.map +1 -0
- package/dist/categories/determinism.js +78 -0
- package/dist/categories/determinism.js.map +1 -0
- package/dist/categories/dsa.d.ts +17 -0
- package/dist/categories/dsa.d.ts.map +1 -0
- package/dist/categories/dsa.js +17 -0
- package/dist/categories/dsa.js.map +1 -0
- package/dist/categories/helpers.d.ts +50 -0
- package/dist/categories/helpers.d.ts.map +1 -0
- package/dist/categories/helpers.js +127 -0
- package/dist/categories/helpers.js.map +1 -0
- package/dist/categories/implicit-rejection.d.ts +29 -0
- package/dist/categories/implicit-rejection.d.ts.map +1 -0
- package/dist/categories/implicit-rejection.js +126 -0
- package/dist/categories/implicit-rejection.js.map +1 -0
- package/dist/categories/index.d.ts +30 -0
- package/dist/categories/index.d.ts.map +1 -0
- package/dist/categories/index.js +33 -0
- package/dist/categories/index.js.map +1 -0
- package/dist/categories/kat.d.ts +21 -0
- package/dist/categories/kat.d.ts.map +1 -0
- package/dist/categories/kat.js +173 -0
- package/dist/categories/kat.js.map +1 -0
- package/dist/categories/robustness.d.ts +15 -0
- package/dist/categories/robustness.d.ts.map +1 -0
- package/dist/categories/robustness.js +98 -0
- package/dist/categories/robustness.js.map +1 -0
- package/dist/categories/signature.d.ts +29 -0
- package/dist/categories/signature.d.ts.map +1 -0
- package/dist/categories/signature.js +259 -0
- package/dist/categories/signature.js.map +1 -0
- package/dist/categories/sizes.d.ts +23 -0
- package/dist/categories/sizes.d.ts.map +1 -0
- package/dist/categories/sizes.js +150 -0
- package/dist/categories/sizes.js.map +1 -0
- package/dist/categories/slh-dsa.d.ts +23 -0
- package/dist/categories/slh-dsa.d.ts.map +1 -0
- package/dist/categories/slh-dsa.js +23 -0
- package/dist/categories/slh-dsa.js.map +1 -0
- package/dist/categories/timing.d.ts +16 -0
- package/dist/categories/timing.d.ts.map +1 -0
- package/dist/categories/timing.js +98 -0
- package/dist/categories/timing.js.map +1 -0
- package/dist/categories/types.d.ts +68 -0
- package/dist/categories/types.d.ts.map +1 -0
- package/dist/categories/types.js +31 -0
- package/dist/categories/types.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +181 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +169 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +115 -0
- package/dist/protocol.js.map +1 -0
- package/dist/report.d.ts +48 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +79 -0
- package/dist/report.js.map +1 -0
- package/dist/runner.d.ts +129 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +305 -0
- package/dist/runner.js.map +1 -0
- package/dist/sizes.d.ts +84 -0
- package/dist/sizes.d.ts.map +1 -0
- package/dist/sizes.js +214 -0
- package/dist/sizes.js.map +1 -0
- package/dist/vectors.d.ts +69 -0
- package/dist/vectors.d.ts.map +1 -0
- package/dist/vectors.js +198 -0
- package/dist/vectors.js.map +1 -0
- package/package.json +43 -0
- package/vectors/README.md +83 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader for OFFICIAL NIST ACVP Known-Answer-Test (KAT) vector files.
|
|
3
|
+
*
|
|
4
|
+
* HONESTY NOTE: Sieve ships NO cryptographic test vectors. It does not and must
|
|
5
|
+
* not fabricate expected pk/sk/ct/ss/sig bytes. This module only PARSES vector
|
|
6
|
+
* files that the user downloads from NIST and points Sieve at via --vectors.
|
|
7
|
+
* See vectors/README.md for where to obtain them and the file format.
|
|
8
|
+
*
|
|
9
|
+
* Supported input: the NIST ACVP-server JSON format for ML-KEM (keyGen,
|
|
10
|
+
* encapDecap) and ML-DSA (keyGen, sigGen, sigVer). The ACVP JSON encodes bytes
|
|
11
|
+
* as hex strings. We normalize the fields we need into a flat list of typed
|
|
12
|
+
* test cases. Anything we don't recognize is ignored (not invented).
|
|
13
|
+
*
|
|
14
|
+
* Uses only node:fs. No cryptography.
|
|
15
|
+
*/
|
|
16
|
+
import type { ParamSet } from "./sizes.js";
|
|
17
|
+
/** A normalized ML-KEM keygen vector: seed -> (pk, sk). */
|
|
18
|
+
export interface KemKeygenVector {
|
|
19
|
+
kind: "kem-keygen";
|
|
20
|
+
param: ParamSet;
|
|
21
|
+
/** Concatenated d||z seed (hex-decoded). */
|
|
22
|
+
seed?: Uint8Array;
|
|
23
|
+
pk: Uint8Array;
|
|
24
|
+
sk: Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
/** A normalized ML-KEM encapsulation vector: (pk, coins) -> (ct, ss). */
|
|
27
|
+
export interface KemEncapVector {
|
|
28
|
+
kind: "kem-encap";
|
|
29
|
+
param: ParamSet;
|
|
30
|
+
pk: Uint8Array;
|
|
31
|
+
/** Encapsulation coins/message m (hex-decoded), if present. */
|
|
32
|
+
coins?: Uint8Array;
|
|
33
|
+
ct: Uint8Array;
|
|
34
|
+
ss: Uint8Array;
|
|
35
|
+
}
|
|
36
|
+
/** A normalized ML-KEM decapsulation vector: (sk, ct) -> ss. */
|
|
37
|
+
export interface KemDecapVector {
|
|
38
|
+
kind: "kem-decap";
|
|
39
|
+
param: ParamSet;
|
|
40
|
+
sk: Uint8Array;
|
|
41
|
+
ct: Uint8Array;
|
|
42
|
+
ss: Uint8Array;
|
|
43
|
+
}
|
|
44
|
+
/** A normalized ML-DSA signature-verification vector: (pk, msg, sig) -> ok. */
|
|
45
|
+
export interface DsaVerifyVector {
|
|
46
|
+
kind: "dsa-verify";
|
|
47
|
+
param: ParamSet;
|
|
48
|
+
pk: Uint8Array;
|
|
49
|
+
msg: Uint8Array;
|
|
50
|
+
sig: Uint8Array;
|
|
51
|
+
expected: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** Any normalized vector. */
|
|
54
|
+
export type Vector = KemKeygenVector | KemEncapVector | KemDecapVector | DsaVerifyVector;
|
|
55
|
+
/** Result of scanning a vectors directory. */
|
|
56
|
+
export interface VectorSet {
|
|
57
|
+
vectors: Vector[];
|
|
58
|
+
/** Files that were read. */
|
|
59
|
+
files: string[];
|
|
60
|
+
/** Non-fatal parse notes (unrecognized files/groups). */
|
|
61
|
+
notes: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Load and normalize all `*.json` ACVP vector files in `dir`.
|
|
65
|
+
*
|
|
66
|
+
* @throws if `dir` does not exist or contains no readable JSON files.
|
|
67
|
+
*/
|
|
68
|
+
export declare function loadVectors(dir: string): VectorSet;
|
|
69
|
+
//# sourceMappingURL=vectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vectors.d.ts","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,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,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;CACjB;AAgJD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAgClD"}
|
package/dist/vectors.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader for OFFICIAL NIST ACVP Known-Answer-Test (KAT) vector files.
|
|
3
|
+
*
|
|
4
|
+
* HONESTY NOTE: Sieve ships NO cryptographic test vectors. It does not and must
|
|
5
|
+
* not fabricate expected pk/sk/ct/ss/sig bytes. This module only PARSES vector
|
|
6
|
+
* files that the user downloads from NIST and points Sieve at via --vectors.
|
|
7
|
+
* See vectors/README.md for where to obtain them and the file format.
|
|
8
|
+
*
|
|
9
|
+
* Supported input: the NIST ACVP-server JSON format for ML-KEM (keyGen,
|
|
10
|
+
* encapDecap) and ML-DSA (keyGen, sigGen, sigVer). The ACVP JSON encodes bytes
|
|
11
|
+
* as hex strings. We normalize the fields we need into a flat list of typed
|
|
12
|
+
* test cases. Anything we don't recognize is ignored (not invented).
|
|
13
|
+
*
|
|
14
|
+
* Uses only node:fs. No cryptography.
|
|
15
|
+
*/
|
|
16
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
function hexToBytes(hex) {
|
|
19
|
+
const clean = hex.trim();
|
|
20
|
+
if (clean.length === 0)
|
|
21
|
+
return new Uint8Array(0);
|
|
22
|
+
if (clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {
|
|
23
|
+
throw new Error(`invalid hex string (len ${clean.length})`);
|
|
24
|
+
}
|
|
25
|
+
const out = new Uint8Array(clean.length / 2);
|
|
26
|
+
for (let i = 0; i < out.length; i++) {
|
|
27
|
+
out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
/** Map an ACVP parameterSet string to our canonical ParamSet, or undefined. */
|
|
32
|
+
function normParam(family, raw) {
|
|
33
|
+
if (typeof raw !== "string")
|
|
34
|
+
return undefined;
|
|
35
|
+
const s = raw.toLowerCase().replace(/_/g, "-");
|
|
36
|
+
// ACVP uses e.g. "ML-KEM-768", "ML-DSA-65".
|
|
37
|
+
const candidates = {
|
|
38
|
+
"ml-kem-512": "ml-kem-512",
|
|
39
|
+
"ml-kem-768": "ml-kem-768",
|
|
40
|
+
"ml-kem-1024": "ml-kem-1024",
|
|
41
|
+
"ml-dsa-44": "ml-dsa-44",
|
|
42
|
+
"ml-dsa-65": "ml-dsa-65",
|
|
43
|
+
"ml-dsa-87": "ml-dsa-87",
|
|
44
|
+
};
|
|
45
|
+
const hit = candidates[s];
|
|
46
|
+
if (hit && hit.startsWith(family))
|
|
47
|
+
return hit;
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
function asArray(v) {
|
|
51
|
+
return Array.isArray(v) ? v : [];
|
|
52
|
+
}
|
|
53
|
+
function asObj(v) {
|
|
54
|
+
return typeof v === "object" && v !== null ? v : {};
|
|
55
|
+
}
|
|
56
|
+
function str(v) {
|
|
57
|
+
return typeof v === "string" ? v : undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse one ACVP test-vectors JSON document into normalized vectors.
|
|
61
|
+
* The ACVP shape is: { algorithm, mode, testGroups: [{ parameterSet, tests:[...] }] }.
|
|
62
|
+
*/
|
|
63
|
+
function parseAcvpDocument(doc, notes, file) {
|
|
64
|
+
const root = asObj(doc);
|
|
65
|
+
const algorithm = str(root["algorithm"])?.toUpperCase() ?? "";
|
|
66
|
+
const mode = str(root["mode"])?.toLowerCase() ?? "";
|
|
67
|
+
const out = [];
|
|
68
|
+
const family = algorithm.includes("KEM")
|
|
69
|
+
? "ml-kem"
|
|
70
|
+
: algorithm.includes("DSA")
|
|
71
|
+
? "ml-dsa"
|
|
72
|
+
: undefined;
|
|
73
|
+
if (family === undefined) {
|
|
74
|
+
notes.push(`${file}: unrecognized algorithm "${algorithm}", skipped`);
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
for (const groupRaw of asArray(root["testGroups"])) {
|
|
78
|
+
const group = asObj(groupRaw);
|
|
79
|
+
const param = normParam(family, group["parameterSet"]);
|
|
80
|
+
if (param === undefined) {
|
|
81
|
+
notes.push(`${file}: skipped group with parameterSet=${String(group["parameterSet"])}`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const fn = str(group["function"])?.toLowerCase(); // encapDecap: "encapsulation"/"decapsulation"
|
|
85
|
+
for (const testRaw of asArray(group["tests"])) {
|
|
86
|
+
const t = asObj(testRaw);
|
|
87
|
+
try {
|
|
88
|
+
if (family === "ml-kem") {
|
|
89
|
+
if (mode.includes("keygen")) {
|
|
90
|
+
const d = str(t["d"]);
|
|
91
|
+
const z = str(t["z"]);
|
|
92
|
+
const seedHex = str(t["seed"]) ?? (d && z ? d + z : undefined);
|
|
93
|
+
out.push({
|
|
94
|
+
kind: "kem-keygen",
|
|
95
|
+
param,
|
|
96
|
+
...(seedHex ? { seed: hexToBytes(seedHex) } : {}),
|
|
97
|
+
pk: hexToBytes(reqHex(t, "ek", "pk")),
|
|
98
|
+
sk: hexToBytes(reqHex(t, "dk", "sk")),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
else if (mode.includes("encapdecap") || mode.includes("encap")) {
|
|
102
|
+
// function may distinguish encapsulation vs decapsulation cases.
|
|
103
|
+
if (fn === "decapsulation" || ("dk" in t && "c" in t)) {
|
|
104
|
+
out.push({
|
|
105
|
+
kind: "kem-decap",
|
|
106
|
+
param,
|
|
107
|
+
sk: hexToBytes(reqHex(t, "dk", "sk")),
|
|
108
|
+
ct: hexToBytes(reqHex(t, "c", "ct")),
|
|
109
|
+
ss: hexToBytes(reqHex(t, "k", "ss")),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const m = str(t["m"]);
|
|
114
|
+
out.push({
|
|
115
|
+
kind: "kem-encap",
|
|
116
|
+
param,
|
|
117
|
+
pk: hexToBytes(reqHex(t, "ek", "pk")),
|
|
118
|
+
...(m ? { coins: hexToBytes(m) } : {}),
|
|
119
|
+
ct: hexToBytes(reqHex(t, "c", "ct")),
|
|
120
|
+
ss: hexToBytes(reqHex(t, "k", "ss")),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
notes.push(`${file}: unrecognized ML-KEM mode "${mode}"`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// ML-DSA: we can robustly check sigVer cases (no nonce dependence).
|
|
130
|
+
if (mode.includes("sigver") || ("signature" in t && "pk" in t)) {
|
|
131
|
+
const expected = t["testPassed"];
|
|
132
|
+
out.push({
|
|
133
|
+
kind: "dsa-verify",
|
|
134
|
+
param,
|
|
135
|
+
pk: hexToBytes(reqHex(t, "pk", "ek")),
|
|
136
|
+
msg: hexToBytes(reqHex(t, "message", "msg")),
|
|
137
|
+
sig: hexToBytes(reqHex(t, "signature", "sig")),
|
|
138
|
+
expected: typeof expected === "boolean" ? expected : true,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
notes.push(`${file}: ML-DSA mode "${mode}" not used for KAT (sign is nonce-dependent)`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
notes.push(`${file}: skipped a test case: ${err.message}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
/** Read the first present hex field among `keys`, else throw. */
|
|
154
|
+
function reqHex(t, ...keys) {
|
|
155
|
+
for (const k of keys) {
|
|
156
|
+
const v = str(t[k]);
|
|
157
|
+
if (v !== undefined)
|
|
158
|
+
return v;
|
|
159
|
+
}
|
|
160
|
+
throw new Error(`missing field (any of: ${keys.join(", ")})`);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Load and normalize all `*.json` ACVP vector files in `dir`.
|
|
164
|
+
*
|
|
165
|
+
* @throws if `dir` does not exist or contains no readable JSON files.
|
|
166
|
+
*/
|
|
167
|
+
export function loadVectors(dir) {
|
|
168
|
+
const st = statSync(dir); // throws ENOENT if missing
|
|
169
|
+
if (!st.isDirectory()) {
|
|
170
|
+
throw new Error(`--vectors path is not a directory: ${dir}`);
|
|
171
|
+
}
|
|
172
|
+
const entries = readdirSync(dir).filter((f) => f.toLowerCase().endsWith(".json"));
|
|
173
|
+
if (entries.length === 0) {
|
|
174
|
+
throw new Error(`no .json vector files found in ${dir}`);
|
|
175
|
+
}
|
|
176
|
+
const vectors = [];
|
|
177
|
+
const files = [];
|
|
178
|
+
const notes = [];
|
|
179
|
+
for (const name of entries) {
|
|
180
|
+
const path = join(dir, name);
|
|
181
|
+
let doc;
|
|
182
|
+
try {
|
|
183
|
+
doc = JSON.parse(readFileSync(path, "utf8"));
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
notes.push(`${name}: not valid JSON (${err.message})`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
files.push(name);
|
|
190
|
+
// ACVP test-vector files may be a single object or an array of prompts.
|
|
191
|
+
const docs = Array.isArray(doc) ? doc : [doc];
|
|
192
|
+
for (const d of docs) {
|
|
193
|
+
vectors.push(...parseAcvpDocument(d, notes, name));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return { vectors, files, notes };
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=vectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../src/vectors.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quantakrypto/sieve",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Sieve — conformance battery for ML-KEM / ML-DSA implementations. Drives any implementation over a simple stdin/stdout JSON protocol. Zero runtime dependencies.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Dandelion Labs <hello@dandelionlabs.io> (https://dandelionlabs.io)",
|
|
7
|
+
"homepage": "https://github.com/dandelionlabs-io/qproof-tools/tree/main/packages/sieve#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/dandelionlabs-io/qproof-tools.git",
|
|
11
|
+
"directory": "packages/sieve"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/dandelionlabs-io/qproof-tools/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"bin": {
|
|
18
|
+
"sieve": "./dist/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"vectors",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -b",
|
|
41
|
+
"test": "node --import tsx --test test/*.test.ts"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Official KAT / ACVP vectors
|
|
2
|
+
|
|
3
|
+
**Sieve ships no cryptographic test vectors.** This directory is where *you*
|
|
4
|
+
place official NIST vector files so the `kat` category can run exact-value
|
|
5
|
+
checks. Without `--vectors <dir>`, the `kat` category is **SKIPPED** — Sieve
|
|
6
|
+
will not invent expected values.
|
|
7
|
+
|
|
8
|
+
## Where to get them
|
|
9
|
+
|
|
10
|
+
Use the **NIST ACVP (Automated Cryptographic Validation Protocol) test
|
|
11
|
+
vectors**, which cover ML-KEM (FIPS 203) and ML-DSA (FIPS 204):
|
|
12
|
+
|
|
13
|
+
- **ACVP test vectors (recommended):**
|
|
14
|
+
<https://github.com/usnistgov/ACVP-Server> — under
|
|
15
|
+
`gen-val/json-files/`, e.g. `ML-KEM-encapDecap-FIPS203/`,
|
|
16
|
+
`ML-KEM-keyGen-FIPS203/`, `ML-DSA-sigVer-FIPS204/`,
|
|
17
|
+
`ML-DSA-keyGen-FIPS204/`. Each folder contains an
|
|
18
|
+
`internalProjection.json` / `prompt.json` / `expectedResults.json` set.
|
|
19
|
+
- **ACVTS demo / production** servers publish the same format.
|
|
20
|
+
- The **CAVP** program pages link to the current vector packages:
|
|
21
|
+
<https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program>.
|
|
22
|
+
|
|
23
|
+
Always verify you downloaded vectors from an authoritative NIST source. Do not
|
|
24
|
+
trust vectors of unknown provenance for conformance claims.
|
|
25
|
+
|
|
26
|
+
## How to use them
|
|
27
|
+
|
|
28
|
+
1. Download the relevant ACVP JSON files for your parameter set.
|
|
29
|
+
2. Drop the `*.json` files into a directory (this one, or any path).
|
|
30
|
+
3. Run Sieve with `--vectors`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
sieve --impl "node ./my-impl.js" --param ml-kem-768 --vectors ./vectors
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Only vectors whose `parameterSet` matches `--param` are used; the rest are
|
|
37
|
+
ignored (and noted).
|
|
38
|
+
|
|
39
|
+
## Expected file format
|
|
40
|
+
|
|
41
|
+
The loader (`src/vectors.ts`) parses the **standard NIST ACVP test-vector
|
|
42
|
+
JSON**. The relevant shape is:
|
|
43
|
+
|
|
44
|
+
```jsonc
|
|
45
|
+
{
|
|
46
|
+
"algorithm": "ML-KEM", // or "ML-DSA"
|
|
47
|
+
"mode": "encapDecap", // or "keyGen", "sigVer", ...
|
|
48
|
+
"testGroups": [
|
|
49
|
+
{
|
|
50
|
+
"parameterSet": "ML-KEM-768",
|
|
51
|
+
"function": "decapsulation", // for encapDecap groups
|
|
52
|
+
"tests": [
|
|
53
|
+
{ "dk": "<hex>", "c": "<hex>", "k": "<hex>" } // sk, ct, ss
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Bytes are **hex** strings in ACVP. The loader normalizes the fields it
|
|
61
|
+
recognizes into typed cases:
|
|
62
|
+
|
|
63
|
+
| ACVP `mode` / fields | Sieve check | What is asserted |
|
|
64
|
+
|-------------------------------------|--------------------|------------------|
|
|
65
|
+
| `keyGen` with `d`+`z` (or `seed`), `ek`, `dk` | `kem-keygen` | seeded keygen reproduces `pk`/`sk` (skipped if the SUT can't seed) |
|
|
66
|
+
| `encapDecap` (encapsulation), `ek`, `m`, `c`, `k` | `kem-encap` | with `coins=m`, deterministic encaps reproduces `ct`/`ss` (skipped if no coins support) |
|
|
67
|
+
| `encapDecap` (decapsulation), `dk`, `c`, `k` | `kem-decap` | `decaps(sk, ct)` equals expected `ss` |
|
|
68
|
+
| `sigVer`, `pk`, `message`, `signature`, `testPassed` | `dsa-verify` | `verify(pk, msg, sig)` equals `testPassed` |
|
|
69
|
+
|
|
70
|
+
> **Note on ML-DSA signing.** ML-DSA `sign` is randomized (hedged), so signature
|
|
71
|
+
> bytes are not reproducible without the exact private randomness. Sieve
|
|
72
|
+
> therefore uses ACVP **sigVer** vectors (verification verdicts) for ML-DSA KAT,
|
|
73
|
+
> not sigGen, and exercises sign/verify self-consistency separately in the `dsa`
|
|
74
|
+
> category.
|
|
75
|
+
|
|
76
|
+
Unrecognized files, algorithms, or fields are recorded as non-fatal notes and
|
|
77
|
+
skipped — Sieve never fabricates a value to fill a gap.
|
|
78
|
+
|
|
79
|
+
## `.gitkeep`
|
|
80
|
+
|
|
81
|
+
This directory is intentionally tracked (so `files` in `package.json` can ship
|
|
82
|
+
this README) but contains no vectors. Add your own; do not commit
|
|
83
|
+
redistributed NIST files unless their license permits it.
|