/* RFC-0565: DHT entry signing and verification — canonicalization and sign/verify wrappers for DHTSiteEntry, built on the existing Ed25519 signBytes/verifyBytes primitives from sign.ts. Analogous to identity-sign.ts but for the DHT site entry shape. Do not handle key storage or management — private keys arrive as env vars. Do not assemble W3C VC envelopes — DHT entries use a simple signature string, not VCProof. Do not modify sign.ts — this module wraps signBytes/verifyBytes. RFC-0565: initial DHT entry signing module. */ /** * @warpgogol/werkstatt-shared/passport/dht-sign — DHT entry signing (RFC-0565) * * Uses signBytes/verifyBytes from sign.ts with a dedicated canonicalization * function for DHT site entries. The signature field is excluded from * canonicalization (it is computed over the entry data without the signature). */ import { signBytes, verifyBytes } from "./sign.ts"; import type { DHTSiteEntry } from "@warpgogol/werkstatt-shared/ontology/operations"; /** * DHTSiteEntry without the signature field — the data that is actually signed. */ export type DHTEntryData = Omit; /** * Produce canonical UTF-8 bytes from a DHT entry (excluding signature). * DETERMINISM: identical inputs → identical bytes (sorted-key JSON, no whitespace). */ export function dhtEntryBytes(entry: DHTEntryData): Uint8Array { const sorted: Record = {}; for (const key of Object.keys(entry).sort()) { sorted[key] = (entry as Record)[key]; } const canonical = JSON.stringify(sorted); return new TextEncoder().encode(canonical); } /** * Sign a DHT entry and return a multibase Ed25519 signature string. * * @param entry — DHT entry data (without signature) * @param privateKeyHex — 32-byte Ed25519 private key as hex (from env secret) * @returns multibase base58btc signature string */ export async function signDhtEntry(entry: DHTEntryData, privateKeyHex: string): Promise { return signBytes(privateKeyHex, dhtEntryBytes(entry)); } /** * Verify a DHT entry signature against the published public key. * * @param entry — full DHT site entry (including signature) * @param publicKeyMultibase — multibase public key from werkstatt.identity.json * @returns true if signature is valid */ export async function verifyDhtEntry( entry: DHTSiteEntry, publicKeyMultibase: string, ): Promise { const { signature, ...entryData } = entry; return verifyBytes(publicKeyMultibase, dhtEntryBytes(entryData), signature); }