Checkpoint: current Lumen state
Some checks failed
ci / check (push) Has been cancelled

This commit is contained in:
Lumen Stage1 2026-09-23 18:58:21 -05:00
commit fcc18ddcc8
96 changed files with 8074 additions and 214 deletions

64
pipeline/sign.ts Normal file
View 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)}`;
}