This commit is contained in:
parent
8e71537d57
commit
fcc18ddcc8
96 changed files with 8074 additions and 214 deletions
64
pipeline/sign.ts
Normal file
64
pipeline/sign.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* Signing seam — Ed25519 over sha256(manifest exact bytes).
|
||||
* Pipeline produces signature.json; verification is Stage 7 (pure-JS verifier).
|
||||
* This module provides a *test-only* signing interface using Node's Ed25519.
|
||||
* Trace: ARCH 10.5, SPIKE-04 F-5, IMPLEMENTATION-CONTRACT.md §11 — Do NOT invent production key custody
|
||||
*/
|
||||
import { createHash, generateKeyPairSync, sign } from "node:crypto";
|
||||
import { sha256Hex } from "./hash.js";
|
||||
import type { PackageSignature } from "../src/data/festival-package/types.js";
|
||||
|
||||
export interface KeyPair {
|
||||
readonly publicKeyDerBase64: string; // SPKI DER base64 for fingerprint derivation
|
||||
readonly privateKeyPem: string; // PKCS8 PEM
|
||||
readonly publicKeyPem: string;
|
||||
readonly fingerprint: string; // "sha256:<hex of SPKI DER>"
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a fresh Ed25519 key pair for tests. Not production key custody.
|
||||
*/
|
||||
export function generateTestKeyPair(): KeyPair {
|
||||
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
||||
const pubDer = publicKey.export({ format: "der", type: "spki" });
|
||||
const pubPem = publicKey.export({ format: "pem", type: "spki" }).toString();
|
||||
const privPem = privateKey.export({ format: "pem", type: "pkcs8" }).toString();
|
||||
const fpHex = sha256Hex(pubDer);
|
||||
return {
|
||||
publicKeyDerBase64: pubDer.toString("base64"),
|
||||
privateKeyPem: privPem as unknown as string,
|
||||
publicKeyPem: pubPem as unknown as string,
|
||||
fingerprint: `sha256:${fpHex}`,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Import private key PEM and sign manifest bytes (exact canonical bytes).
|
||||
*/
|
||||
export function signManifest(
|
||||
manifestBytes: Uint8Array,
|
||||
privateKeyPem: string,
|
||||
publicKeyFingerprint: string,
|
||||
): PackageSignature {
|
||||
const manifestDigest = createHash("sha256").update(manifestBytes).digest();
|
||||
const sig = sign(null, manifestDigest, { key: privateKeyPem, format: "pem", type: "pkcs8" });
|
||||
const sigB64 = sig.toString("base64");
|
||||
const manifestSha256 = sha256Hex(manifestBytes);
|
||||
return {
|
||||
algorithm: "ed25519",
|
||||
over: "sha256(manifest.json exact bytes)",
|
||||
manifestSha256,
|
||||
publicKeyFingerprint,
|
||||
signature: sigB64,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive fingerprint from public key PEM (for verification side).
|
||||
*/
|
||||
export function fingerprintFromPublicPem(publicKeyPem: string): string {
|
||||
const { createPublicKey } = require("node:crypto") as typeof import("node:crypto");
|
||||
const key = createPublicKey(publicKeyPem);
|
||||
const der = key.export({ format: "der", type: "spki" }) as Buffer;
|
||||
return `sha256:${sha256Hex(der)}`;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue