Merkle
leafHash / nodeHash / emptyRootHash build the tree hashes with the two domain-separation prefixes fixed by the spec -- a leaf is SHA-256(0x00 || entry), an interior node is SHA-256(0x01 || left || right), the empty tree is SHA-256(""). Those 0x00 / 0x01 prefixes are the second-preimage defense: without them a leaf whose bytes equal a valid interior node's preimage could be smuggled in as present.
verifyInclusion folds an audit path back to a root and constant-time- compares it to a trusted checkpoint root; verifyConsistency reconstructs BOTH the old and the new root from a consistency proof (the append-only guarantee lives in the old-root leg). Both are fail-closed: a malformed coordinate, an out-of-range index, an inverted window, a wrong hash length, or a proof whose node count does not match the tree geometry throws a typed merkle/* error; the ONLY boolean-false result is the final root comparison ("root matched" vs "did not"). A false from verifyInclusion means "not proven present against this root", never "validly absent" -- an inclusion proof cannot express absence. Tree coordinates are uint64, carried as BigInt so a large index is never Number-narrowed. This is NOT a DER format: like pki.ct it is a companion module reached explicitly, never routed by the detect-and-parse orchestrator.
pki.merkle.leafHash
pki.merkle.leafHash(entry) -> Buffer
The Merkle leaf hash MTH({d}) = SHA-256(0x00 || entry). The 0x00 prefix is the leaf-domain second-preimage separation and is applied unconditionally. Throws merkle/bad-input if entry is not a Buffer / Uint8Array.
Example
pki.merkle.leafHash(Buffer.from("leaf data")); // -> <Buffer 32-byte leaf hash>
References
pki.merkle.nodeHash
pki.merkle.nodeHash(left, right) -> Buffer
The Merkle interior-node hash SHA-256(0x01 || left || right). Both operands must be 32-byte hashes; the 0x01 prefix is applied unconditionally. Throws merkle/bad-input on a non-buffer operand, merkle/bad-hash-length on an operand that is not exactly 32 bytes.
Example
var l = pki.merkle.leafHash(Buffer.from([0]));
var r = pki.merkle.leafHash(Buffer.from([1]));
pki.merkle.nodeHash(l, r); // -> <Buffer 32-byte node hash>
References
pki.merkle.emptyRootHash
pki.merkle.emptyRootHash() -> Buffer
The Merkle tree head of the empty tree, MTH({}) = SHA-256("") (e3b0c442...b855). A fresh Buffer each call.
Example
pki.merkle.emptyRootHash(); // -> <Buffer e3 b0 c4 42 ...>
References
pki.merkle.verifyInclusion
pki.merkle.verifyInclusion(opts) -> boolean
Verify an RFC 6962 / RFC 9162 audit (inclusion) proof: fold leafHash up the audit path and constant-time-compare the reconstructed root to rootHash. Returns true iff the proof binds the leaf to the root; a well-formed proof that does not match returns false ("not proven present against this root", NEVER "validly absent"). A malformed input -- a coordinate that is not a non-negative integer (or a Number >= 2^53), treeSize 0, leafIndex >= treeSize, a non-32-byte hash, or a proof whose node count does not match the tree geometry -- throws a typed merkle/* error.
Options
leafIndex: number | bigint, // 0-based leaf position (uint64; pass BigInt above 2^53)
treeSize: number | bigint, // total leaf count of the tree the root commits to
leafHash: Buffer, // 32-byte leaf hash (e.g. from pki.merkle.leafHash)
proof: Buffer[], // the audit path, each node a 32-byte hash
rootHash: Buffer, // 32-byte trusted checkpoint root
Example
var lh = pki.merkle.leafHash(Buffer.from([0]));
pki.merkle.verifyInclusion({ leafIndex: 0, treeSize: 1, leafHash: lh, proof: [], rootHash: lh }); // -> true
References
pki.merkle.verifyConsistency
pki.merkle.verifyConsistency(opts) -> boolean
Verify an RFC 6962 / RFC 9162 consistency proof between an older tree of oldSize leaves (root oldRoot) and a newer tree of newSize leaves (root newRoot). Reconstructs BOTH roots from the proof and constant-time-compares each; returns true iff both match (the append-only guarantee lives in the old-root leg -- a proof that yields a valid newRoot but the wrong oldRoot is a rewritten history and returns false). The empty tree is a prefix of every tree, so oldSize 0 checks oldRoot == emptyRootHash() -- and, when newSize is also 0, newRoot == emptyRootHash() too (both trees empty); for newSize > 0 an empty-old proof places no binding on newRoot (an empty prior tree carries no append-only guarantee -- authenticate newRoot separately, e.g. via its checkpoint signature). Equal non-zero sizes require an empty proof and oldRoot == newRoot. A malformed input -- oldSize > newSize, a non-empty proof where the geometry requires none (or empty where it requires one), a non-32-byte hash, or a wrong node count -- throws a typed merkle/* error.
Options
oldSize: number | bigint, // leaf count of the older tree (uint64)
newSize: number | bigint, // leaf count of the newer tree (>= oldSize)
oldRoot: Buffer, // 32-byte root of the older tree
newRoot: Buffer, // 32-byte root of the newer tree
proof: Buffer[], // the consistency proof, each node a 32-byte hash
Example
var r = pki.merkle.leafHash(Buffer.from([0]));
pki.merkle.verifyConsistency({ oldSize: 1, newSize: 1, oldRoot: r, newRoot: r, proof: [] }); // -> true