Initial Commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env bun
|
||||
/**
|
||||
* Deterministic SRP test-vector generator.
|
||||
*
|
||||
* Runs the full SRP-6a handshake (computeVerifier → clientStartHandshake →
|
||||
* serverStartHandshake → clientFinishHandshake → serverFinishHandshake)
|
||||
* for the bundled 2048-bit group with SHA-256, using a fixed-seed
|
||||
* deterministic RNG, and writes the resulting `(x, v, A, B, K, M1, M2)`
|
||||
* tuple to `src/__fixtures__/vectors-2048-sha256.json`.
|
||||
*
|
||||
* Re-running the script with the same seed produces a byte-identical
|
||||
* JSON fixture. The conformance test replays the same handshake against
|
||||
* the committed fixture to anchor the modern 2048/SHA-256 default.
|
||||
*
|
||||
* Usage:
|
||||
* bun scripts/generate-srp-vectors.ts [--seed=42]
|
||||
*/
|
||||
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import type { Rng } from "@suaveplan/types";
|
||||
import { clientFinishHandshake } from "../src/client/client-finish.js";
|
||||
import { clientStartHandshake } from "../src/client/client-start.js";
|
||||
import { nobleHashBridge } from "../src/hash/hash-bridge.js";
|
||||
import { params2048Sha256 } from "../src/params/params.js";
|
||||
import { serverFinishHandshake } from "../src/server/server-finish.js";
|
||||
import { serverStartHandshake } from "../src/server/server-start.js";
|
||||
import { computeVerifier } from "../src/verifier/verifier.js";
|
||||
|
||||
function seededRng(seed: number): Rng {
|
||||
let state = seed >>> 0;
|
||||
return {
|
||||
nextUint32: () => {
|
||||
state = (state * 1664525 + 1013904223) >>> 0;
|
||||
return state;
|
||||
},
|
||||
nextFloat: () => 0.5,
|
||||
nextBytes: (n: number) => {
|
||||
const out = new Uint8Array(n);
|
||||
let i = 0;
|
||||
while (i < n) {
|
||||
state = (state * 1664525 + 1013904223) >>> 0;
|
||||
out[i++] = state & 0xff;
|
||||
if (i < n) out[i++] = (state >>> 8) & 0xff;
|
||||
if (i < n) out[i++] = (state >>> 16) & 0xff;
|
||||
if (i < n) out[i++] = (state >>> 24) & 0xff;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function toHex(bytes: Uint8Array): string {
|
||||
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
||||
}
|
||||
|
||||
function parseSeed(): number {
|
||||
const arg = process.argv.find((a) => a.startsWith("--seed="));
|
||||
if (arg) return Number.parseInt(arg.slice("--seed=".length), 10);
|
||||
return 42;
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const seed = parseSeed();
|
||||
const params = params2048Sha256(nobleHashBridge("SHA256"));
|
||||
const I = "alice@example.com";
|
||||
const P = "correct horse battery staple";
|
||||
const salt = seededRng(seed + 1).nextBytes!(16);
|
||||
const { x, v } = computeVerifier(I, P, salt, params);
|
||||
const { a, A } = clientStartHandshake(seededRng(seed + 2), params);
|
||||
const { b, B } = serverStartHandshake(v, seededRng(seed + 3), params);
|
||||
const client = clientFinishHandshake(I, P, salt, A, B, a, params);
|
||||
const server = serverFinishHandshake(I, salt, A, B, b, v, client.M1, params);
|
||||
|
||||
const fixture = {
|
||||
meta: {
|
||||
group: "RFC 5054 Appendix A 2048-bit",
|
||||
hash: "SHA-256",
|
||||
seed,
|
||||
generator: "scripts/generate-srp-vectors.ts",
|
||||
},
|
||||
inputs: {
|
||||
I,
|
||||
P,
|
||||
salt_hex: toHex(salt),
|
||||
a_hex: toHex(a),
|
||||
b_hex: toHex(b),
|
||||
},
|
||||
outputs: {
|
||||
x_hex: toHex(x),
|
||||
v_hex: toHex(v),
|
||||
A_hex: toHex(A),
|
||||
B_hex: toHex(B),
|
||||
K_hex: toHex(client.K),
|
||||
M1_hex: toHex(client.M1),
|
||||
M2_hex: toHex(server.M2),
|
||||
S_hex: toHex(client.S),
|
||||
},
|
||||
};
|
||||
const outPath = join(
|
||||
dirname(new URL(import.meta.url).pathname),
|
||||
"..",
|
||||
"src",
|
||||
"__fixtures__",
|
||||
"vectors-2048-sha256.json"
|
||||
);
|
||||
mkdirSync(dirname(outPath), { recursive: true });
|
||||
writeFileSync(outPath, `${JSON.stringify(fixture, null, 2)}\n`);
|
||||
console.log(`wrote ${outPath}`);
|
||||
}
|
||||
|
||||
await main();
|
||||
Reference in New Issue
Block a user