mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-09-10 19:26:00 +00:00
M1 of the ANS SDK (docs/ans-sdk.md): - name: parse/format ans://v<semver>.<agent>.<domain> - cbor: minimal RFC 8949 codec for the COSE_Sign1 subset - verify/merkle: RFC 6962 leaf/node hashing, tree build, inclusion-proof generation + verification - verify/es256 + cose: COSE_Sign1 build/parse, Sig_structure, ES256 (WebCrypto) - verify/rootkeys: kid -> verifier key (JWKS entries; sumdb-note is M2) - verify: verifyReceipt() + verifyResolution() (signature + inclusion proof + name binding), pure and offline - client: AnsClient resolve/rootKeys/register/status over injectable fetch, with a DnsApplier hook for verify-dns Tests (24) cover name parsing, CBOR round-trips/vectors, RFC 6962 proofs, a full ES256+Merkle receipt round-trip with positive/negative cases, and the client against mocked fetch. Wired into the root build script. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
30 lines
1 KiB
TypeScript
30 lines
1 KiB
TypeScript
// Transparency-log verifier keys, indexed by 4-byte kid (lowercase hex).
|
|
//
|
|
// M1 accepts a JWKS-style list ({ kid, jwk }). The upstream sumdb-note
|
|
// (`/root-keys`) parser is M2 (TODO) — captured against fixtures.
|
|
|
|
import { importEs256VerifyKey } from './es256.js';
|
|
import { fromHex, toHex } from '../bytes.js';
|
|
import type { RootKeys } from '../types.js';
|
|
|
|
export interface RootKeyEntry {
|
|
/** 4-byte key id as hex (e.g. "01020304") or any string the receipts use. */
|
|
kid: string;
|
|
jwk: JsonWebKey;
|
|
}
|
|
|
|
export async function rootKeysFromEntries(entries: RootKeyEntry[]): Promise<RootKeys> {
|
|
const keys = new Map<string, CryptoKey>();
|
|
for (const entry of entries) {
|
|
const kidHex = normalizeKid(entry.kid);
|
|
keys.set(kidHex, await importEs256VerifyKey(entry.jwk));
|
|
}
|
|
return { keys };
|
|
}
|
|
|
|
/** Accept kid as hex ("01020304") or as already-normalized; lowercases hex. */
|
|
function normalizeKid(kid: string): string {
|
|
const lower = kid.toLowerCase();
|
|
if (/^[0-9a-f]+$/.test(lower) && lower.length % 2 === 0) return toHex(fromHex(lower));
|
|
return lower;
|
|
}
|