import { M as ManifestEntry } from '../bundle-CKS7FPC4.cjs'; /** * JCS (RFC 8785) canonicalization. * * Deterministic JSON serialization. Without this, two servers might * produce different byte strings for the same object, breaking hash * equality and verification. JCS sorts object keys lexically and * uses stable number / string formatting. * * This implementation matches Python's * * json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=False) * * for all JSON-safe values used in EnvelopeV1, STH, and bundle JSON * files. Cross-language parity is a hard invariant — any change here * requires a coordinated update to the Python SDK's equivalent * function and a re-run of the parity fixtures (see * `test/envelope-parity.spec.ts` and `test/sth-parity.spec.ts`). * * Functionally equivalent to `shared-deps/chain/lib/crypto.ts::jcs`. * Reimplemented here rather than imported because: * - the SDK has zero runtime dependencies (shared-deps pulls in * `@aws-sdk/client-kms` for backend signing); * - duplicating ~25 lines is cheaper than a peer-dep treadmill; * - the parity tests cross-validate byte-for-byte against * shared-deps' fixture, so drift is caught at CI time. */ declare function jcs(value: unknown): string; /** * Hash primitives — SHA-256 over Buffers and strings, plus the * canonical envelope-hash and STH-hash entry points. * * Uses `node:crypto` only. Browser / non-Node runtimes are not * supported in v1; if a Phase 2 use case needs them we can swap in * `globalThis.crypto.subtle` behind a thin abstraction. */ declare function sha256(buf: Buffer | Uint8Array | string): Buffer; declare function sha256Hex(buf: Buffer | Uint8Array | string): string; /** * Canonical envelope hash. * * Per ARCHITECTURE.md §5, the envelope does not contain a signature. * Defensively strip any `sig` field before hashing — protects * against dynamic callers (e.g. negative-case tests, or a deserialized * pre-spec envelope) that might include one. * * The result is the value the issuer signs, the value emitted as * `envelope_hash` everywhere, and the value verifiers compare to the * `envelope.hash` file inside a bundle. */ declare function envelopeHash(envelope: Record): string; /** * Canonical STH hash. * * Per ARCHITECTURE.md §6.3, the chain-master signature is stored in * the `master_sig` field on the wire form. Strip both `master_sig` * and the legacy `sig` (defensively, for any pre-M03 STHs that * might still be in flight) before hashing. * * After stripping, JCS sorts the remaining keys lexically — the * preimage byte order is `alg, checkpoint, key_id, root, segment, * timestamp, tree_size, v`. */ declare function sthHash(sth: Record): string; /** * `MANIFEST.txt` serializer + parser. * * Format (per ARCHITECTURE.md §8 D.9): * * <64 hex chars> * * Drop-in compatible with `sha256sum -c MANIFEST.txt` on Linux and * `shasum -a 256 -c MANIFEST.txt` on macOS. Lines are sorted * lexically by `path` so two builds of the same bundle produce * byte-identical MANIFEST contents. * * Hex digests are 64 lowercase characters (256 bits). No `0x` * prefix. Two literal ASCII spaces separate digest from path — * matching GNU coreutils output exactly. Trailing newline after * every entry. * * Paths are bundle-relative POSIX-style with forward slashes * (`timestamps/digicert.tsr`, NOT `timestamps\\digicert.tsr`). The * bundle's zip already enforces forward slashes; manifest paths * inherit. * * Functionally equivalent to * `shared-deps/chain/bundle/manifest.ts`. Reimplemented here for * dependency-zero parity reasons (see `./jcs.ts` rationale). */ /** * Serialize a list of manifest entries to `MANIFEST.txt` text. * * Sorts by `path` (lexical) before emitting so output is * deterministic — re-running on the same input always produces the * same bytes. Sorting is non-mutating; the input array is not * modified. * * Throws if any `sha256` field is not 64 lowercase hex characters, * or if any `path` contains a literal newline. Callers should * validate inputs upstream; this is defense-in-depth. */ declare function serializeManifest(entries: readonly ManifestEntry[]): string; /** * Parse `MANIFEST.txt` text back into entries. * * Strict — rejects: * - lines that don't match the `<64 hex> ` shape * - duplicate paths (the bundle builder never produces duplicates; * a duplicate at parse time means the manifest was tampered * with or hand-edited) * - paths beginning with whitespace (defends against an attacker * padding the separator with extra spaces) * * Tolerates a trailing empty line (CRLF or LF). Does NOT tolerate * arbitrary whitespace around fields — the format is rigid by * design so malicious manifests can't sneak in lookalike paths via * normalization. * * Returns entries in their on-disk order. Callers that need a * canonical order should sort by `path`; `serializeManifest` * round-trips a sort. */ declare function parseManifest(text: string): ManifestEntry[]; /** * True iff `s` is exactly 64 lowercase hex characters. The format * is deliberately strict — uppercase or short digests are rejected * so verifiers can rely on byte-equality of MANIFEST contents * across platforms. */ declare function isValidSha256Hex(s: string): boolean; /** * RFC 6962 Certificate-Transparency-style Merkle tree primitives. * * - Domain-separated leaf and node prefixes (0x00, 0x01) to prevent * second-preimage / length-extension attacks. * - SHA-256 only in v1 (matches shared-deps default; SHA-512 lives * on the backend tree but is irrelevant to v1 verification). * - Verification only: this SDK never builds trees, only walks * audit paths. Tree construction lives in the backend * (`anchor-service` Lambda) and is unnecessary here. * * Mirrors `shared-deps/chain/lib/merkle.ts::leafHash`, * `nodeHash`, `verifyInclusion`. Reimplemented for the same * dependency-zero reasons as `./jcs.ts`. */ /** * Hash a leaf payload (canonical envelope bytes). * * The result is the bundle's `merkle.json::leaf_hash` — NOT the * envelope hash. The two differ by the `0x00` prefix; a verifier * that compares them directly is wrong. */ declare function leafHash(payload: Buffer | Uint8Array): Buffer; /** Hash an internal node from two children. */ declare function nodeHash(left: Buffer, right: Buffer): Buffer; /** * Verify an inclusion proof. * * Recomputes the root from `(leaf, m, n, path)` and compares against * `expectedRoot`. Consumes the path bottom-up (closest-to-leaf first), * matching the RFC 6962 §2.1.1 audit-path format and the order that * the backend's `inclusionProof` produces. * * Handles non-power-of-two sizes correctly: at levels where a subtree * is "promoted" without a sibling (`fn === sn`), the walk keeps * climbing until it encounters the next real sibling. */ declare function verifyInclusion(leaf: Buffer, m: number, n: number, path: Buffer[], expectedRoot: Buffer): boolean; /** * Verify a consistency proof: old root (size m) → new root (size n). * RFC 6962 §2.1.4. * * Used by witness implementations and the consistency-check feature * in the Governance Console (M10). Verification only — no proof * construction in v1. */ declare function verifyConsistency(oldRoot: Buffer, newRoot: Buffer, m: number, n: number, proof: Buffer[]): boolean; declare const hex: (b: Buffer) => string; declare const unhex: (s: string) => Buffer; export { envelopeHash, hex, isValidSha256Hex, jcs, leafHash, nodeHash, parseManifest, serializeManifest, sha256, sha256Hex, sthHash, unhex, verifyConsistency, verifyInclusion };