Class MerkleTreePrimitives
java.lang.Object
org.bouncycastle.cert.plants.MerkleTreePrimitives
Merkle Tree primitives for Merkle Tree Certificates (PLANTS).
Implements the generation and verification of subtree inclusion proofs and
subtree consistency proofs, the Merkle Tree Hash over a range of entries, and
interval covering.
All algorithms are expressed against the MerkleTreeHash operator,
which the caller supplies; there are no direct org.bouncycastle.crypto.*
or java.security.* dependencies in this class.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classSimple container for a subtree interval (start inclusive, end exclusive). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic byte[]computeMerkleTreeHash(List<byte[]> entryHashes, long start, long end, MerkleTreeHash hash) Computes the Merkle Tree HashMTH(D[start:end])over a range of entries, per RFC 9162 Section 2.1.1.static byte[]computeMerkleTreeHash(MerkleTreeNodeSource nodes, long start, long end, MerkleTreeHash hash) Computes the Merkle Tree HashMTH(D[start:end])over a range of entries from a storage-backed tree, per RFC 9162 Section 2.1.1.static byte[]evaluateSubtreeInclusionProof(long index, long start, long end, byte[] entryHash, List<byte[]> proof, MerkleTreeHash hash) Evaluates a subtree inclusion proof, returning the expected subtree hash.static List<long[]> findCoveringSubtrees(long start, long end) Finds the minimal set of subtrees that efficiently cover the interval [start, end).static List<byte[]> generateSubtreeConsistencyProof(long start, long end, long n, List<byte[]> entryHashes, MerkleTreeHash hash) Generates a subtree consistency proofSUBTREE_PROOF(start, end, D_n)showing that the subtree[start, end)is contained in the tree of sizen, per Section 4.4.1.static List<byte[]> generateSubtreeConsistencyProof(long start, long end, long n, MerkleTreeNodeSource nodes, MerkleTreeHash hash) Generates a subtree consistency proofSUBTREE_PROOF(start, end, D_n)for the subtree[start, end)in a storage-backed tree of sizen; seegenerateSubtreeConsistencyProof(long, long, long, List, MerkleTreeHash).static List<byte[]> generateSubtreeInclusionProof(long index, long start, long end, List<byte[]> entryHashes, MerkleTreeHash hash) Generates a subtree inclusion proof for the entry atindexwithin the subtree[start, end).static List<byte[]> generateSubtreeInclusionProof(long index, long start, long end, MerkleTreeNodeSource nodes, MerkleTreeHash hash) Generates a subtree inclusion proof for the entry atindexwithin the subtree[start, end)of a storage-backed tree; seegenerateSubtreeInclusionProof(long, long, long, List, MerkleTreeHash).static booleanisFullSubtree(long start, long end) Whether[start, end)is a full subtree: its size is a power of two andstartis a multiple of that size, soMTH(D[start:end])is a single node of the tree.static booleanisValidSubtree(long start, long end) Checks whether[start, end)is a valid subtree interval per Section 4.1: 0 <= start < end, and start is a multiple of BIT_CEIL(end - start).static booleanverifySubtreeConsistencyProof(long start, long end, long n, byte[] subtreeHash, byte[] rootHash, List<byte[]> proof, MerkleTreeHash hash) Verifies a subtree consistency proof.static booleanverifySubtreeInclusionProof(long index, long start, long end, byte[] entryHash, byte[] subtreeHash, List<byte[]> proof, MerkleTreeHash hash) Verifies a subtree inclusion proof by comparing the evaluated hash with the given subtree hash.
-
Constructor Details
-
MerkleTreePrimitives
public MerkleTreePrimitives()
-
-
Method Details
-
evaluateSubtreeInclusionProof
public static byte[] evaluateSubtreeInclusionProof(long index, long start, long end, byte[] entryHash, List<byte[]> proof, MerkleTreeHash hash) throws InvalidProofException Evaluates a subtree inclusion proof, returning the expected subtree hash.- Parameters:
index- absolute index of the entry in the logstart- subtree start index (inclusive)end- subtree end index (exclusive)entryHash- hash of the entry (MTH({entry}))proof- list of node hashes forming the inclusion proofhash- the Merkle tree hash implementation- Returns:
- the expected subtree hash
- Throws:
InvalidProofException- if the proof is malformed or cannot be evaluated- See Also:
-
verifySubtreeInclusionProof
public static boolean verifySubtreeInclusionProof(long index, long start, long end, byte[] entryHash, byte[] subtreeHash, List<byte[]> proof, MerkleTreeHash hash) Verifies a subtree inclusion proof by comparing the evaluated hash with the given subtree hash.- Parameters:
index- absolute index of the entrystart- subtree startend- subtree endentryHash- hash of the entrysubtreeHash- claimed subtree hashproof- inclusion proofhash- hash implementation- Returns:
- true if the proof is valid, false otherwise
-
verifySubtreeConsistencyProof
public static boolean verifySubtreeConsistencyProof(long start, long end, long n, byte[] subtreeHash, byte[] rootHash, List<byte[]> proof, MerkleTreeHash hash) Verifies a subtree consistency proof.- Parameters:
start- subtree start indexend- subtree end index (exclusive)n- full tree size (number of entries)subtreeHash- hash of the subtree (MTH(D[start:end]))rootHash- hash of the full tree (MTH(D[0:n]))proof- list of node hashes forming the consistency proofhash- hash implementation- Returns:
- true if the proof is valid, false otherwise
- See Also:
-
computeMerkleTreeHash
public static byte[] computeMerkleTreeHash(List<byte[]> entryHashes, long start, long end, MerkleTreeHash hash) Computes the Merkle Tree HashMTH(D[start:end])over a range of entries, per RFC 9162 Section 2.1.1. The range need not be a subtree in the sense of Section 4.1; any non-empty[start, end)within the list is accepted, which is what the proof generators need for the intermediate node hashes they emit.- Parameters:
entryHashes- hashes of the tree's entries, entryiat positioni(eachMTH({entry}), i.e.MerkleTreeHash.hashLeaf(byte[]))start- range start index (inclusive)end- range end index (exclusive)hash- the Merkle tree hash implementation- Returns:
MTH(D[start:end])- Throws:
IllegalArgumentException- if the range is empty or not covered byentryHashes
-
computeMerkleTreeHash
public static byte[] computeMerkleTreeHash(MerkleTreeNodeSource nodes, long start, long end, MerkleTreeHash hash) Computes the Merkle Tree HashMTH(D[start:end])over a range of entries from a storage-backed tree, per RFC 9162 Section 2.1.1. A range that is itself a full subtree is a single request tonodes; any other range is combined from at most one full subtree per level of the tree.- Parameters:
nodes- source of full-subtree hashes for the treestart- range start index (inclusive)end- range end index (exclusive)hash- the Merkle tree hash implementation- Returns:
MTH(D[start:end])- Throws:
IllegalArgumentException- if the range is empty, ornodescannot supply a node
-
generateSubtreeInclusionProof
public static List<byte[]> generateSubtreeInclusionProof(long index, long start, long end, List<byte[]> entryHashes, MerkleTreeHash hash) Generates a subtree inclusion proof for the entry atindexwithin the subtree[start, end). Per Section 4.3 this is the Merkle inclusion proofPATH(index - start, D[start:end])of RFC 9162 Section 2.1.3.1, computed over the subtree's entries. The result is accepted byevaluateSubtreeInclusionProof(long, long, long, byte[], List, MerkleTreeHash)andverifySubtreeInclusionProof(long, long, long, byte[], byte[], List, MerkleTreeHash)for the sameindex,startandend.- Parameters:
index- absolute index of the entry in the logstart- subtree start index (inclusive)end- subtree end index (exclusive)entryHashes- hashes of the tree's entries, entryiat positioni; only positions[start, end)are readhash- the Merkle tree hash implementation- Returns:
- the sibling hashes from the entry up to the subtree root (empty for a size-one subtree)
- Throws:
IllegalArgumentException- if[start, end)is not a valid subtree (Section 4.1),indexlies outside it, orentryHashesdoes not cover it
-
generateSubtreeInclusionProof
public static List<byte[]> generateSubtreeInclusionProof(long index, long start, long end, MerkleTreeNodeSource nodes, MerkleTreeHash hash) Generates a subtree inclusion proof for the entry atindexwithin the subtree[start, end)of a storage-backed tree; seegenerateSubtreeInclusionProof(long, long, long, List, MerkleTreeHash).- Parameters:
index- absolute index of the entry in the logstart- subtree start index (inclusive)end- subtree end index (exclusive)nodes- source of full-subtree hashes for the tree; only nodes within[start, end)are requestedhash- the Merkle tree hash implementation- Returns:
- the sibling hashes from the entry up to the subtree root (empty for a size-one subtree)
- Throws:
IllegalArgumentException- if[start, end)is not a valid subtree (Section 4.1),indexlies outside it, ornodescannot supply a node
-
generateSubtreeConsistencyProof
public static List<byte[]> generateSubtreeConsistencyProof(long start, long end, long n, List<byte[]> entryHashes, MerkleTreeHash hash) Generates a subtree consistency proofSUBTREE_PROOF(start, end, D_n)showing that the subtree[start, end)is contained in the tree of sizen, per Section 4.4.1. The result is accepted byverifySubtreeConsistencyProof(long, long, long, byte[], byte[], List, MerkleTreeHash)for the samestart,endandn. As the draft notes, withstart == 0this is the RFC 9162 consistency proofPROOF(end, D_n), and withend == start + 1it is the inclusion proofPATH(start, D_n).- Parameters:
start- subtree start index (inclusive)end- subtree end index (exclusive)n- full tree size (number of entries)entryHashes- hashes of the tree's entries, entryiat positioni; positions[0, n)are readhash- the Merkle tree hash implementation- Returns:
- the node hashes forming the consistency proof (empty when the subtree is the whole tree)
- Throws:
IllegalArgumentException- if[start, end)is not a valid subtree (Section 4.1),end > n, orentryHashesdoes not cover[0, n)
-
generateSubtreeConsistencyProof
public static List<byte[]> generateSubtreeConsistencyProof(long start, long end, long n, MerkleTreeNodeSource nodes, MerkleTreeHash hash) Generates a subtree consistency proofSUBTREE_PROOF(start, end, D_n)for the subtree[start, end)in a storage-backed tree of sizen; seegenerateSubtreeConsistencyProof(long, long, long, List, MerkleTreeHash).- Parameters:
start- subtree start index (inclusive)end- subtree end index (exclusive)n- full tree size (number of entries)nodes- source of full-subtree hashes for the tree; only nodes within[0, n)are requestedhash- the Merkle tree hash implementation- Returns:
- the node hashes forming the consistency proof (empty when the subtree is the whole tree)
- Throws:
IllegalArgumentException- if[start, end)is not a valid subtree (Section 4.1),end > n, ornodescannot supply a node
-
isFullSubtree
public static boolean isFullSubtree(long start, long end) Whether[start, end)is a full subtree: its size is a power of two andstartis a multiple of that size, soMTH(D[start:end])is a single node of the tree.- Parameters:
start- subtree start (inclusive)end- subtree end (exclusive)- Returns:
- true if the range is one node of the tree
-
isValidSubtree
public static boolean isValidSubtree(long start, long end) Checks whether[start, end)is a valid subtree interval per Section 4.1: 0 <= start < end, and start is a multiple of BIT_CEIL(end - start).- Parameters:
start- subtree start (inclusive)end- subtree end (exclusive)- Returns:
- true if the interval describes a valid subtree
-
findCoveringSubtrees
Finds the minimal set of subtrees that efficiently cover the interval [start, end). Returns a list of one or two (start, end) pairs.- Parameters:
start- start index of the interval (inclusive)end- end index of the interval (exclusive)- Returns:
- list of one or two subtrees covering the interval (as long arrays of length 2)
- See Also:
-