2.6 KiB
inclusion-proof
Purpose
Verifies an RFC 6962 Merkle inclusion proof as returned by Sigstore Rekor. Given a leaf (the canonical body a Rekor entry was logged as), a sibling audit path, the leaf's log index, the tree size at inclusion time, and the signed root hash, recomputes the root and confirms it matches. This is the cryptographic half of Rekor trust — once the root matches, the transparency log has published the entry and cannot later lie about having done so.
Features
- RFC 6962 hashing with explicit domain separators (
0x00for leaves,0x01for interior nodes). - Correct handling of last-node-at-level carrying (odd tree sizes).
- Structured
RekorInclusionErrorwhenlogIndexis out of range. - Exposes
rfc6962LeafHashfor batch / cache use-cases.
Usage: Basic Example
import { verifyRfc6962InclusionProof } from "@suaveplan/slsa";
const { valid, computedRootHex } = verifyRfc6962InclusionProof({
leafBytes: new TextEncoder().encode(entry.body),
hashes: entry.verification.inclusionProof.hashes,
logIndex: entry.logIndex,
treeSize: entry.verification.inclusionProof.treeSize,
expectedRootHex: entry.verification.inclusionProof.rootHash,
});
Usage: Advanced Example
import {
RekorClient,
rfc6962LeafHash,
verifyRfc6962InclusionProof,
} from "@suaveplan/slsa";
const client = new RekorClient();
const entry = await client.uploadHashedrekord(rekord);
const leafBytes = new TextEncoder().encode(entry.body);
const leafHex = rfc6962LeafHash(leafBytes);
log.info({ leafHex, logIndex: entry.logIndex }, "rekor entry hashed");
const proof = entry.verification?.inclusionProof;
if (proof) {
const { valid } = verifyRfc6962InclusionProof({
leafBytes,
hashes: proof.hashes,
logIndex: entry.logIndex,
treeSize: proof.treeSize,
expectedRootHex: proof.rootHash,
});
if (!valid) throw new Error("inclusion failed");
}
API Reference
verifyRfc6962InclusionProof(args): { valid, computedRootHex }— returns whether the computed root matches. ThrowsRekorInclusionErrorwhenlogIndex >= treeSizeorlogIndex < 0.rfc6962LeafHash(body: Uint8Array): string— lowercase hex SHA-256 with the0x00leaf prefix.
Implementation Notes
The carry-up branch (odd-count level) handles trees where the last node at a given level has no sibling — rather than duplicating, RFC 6962 propagates the node up unchanged. Rekor's server-side proof generator will either produce a shorter path for such leaves or include a duplicate; this implementation tolerates the former. String comparison is case-insensitive on the expected root to match Sigstore's mixed-case hex output.