Package org.bouncycastle.cert.plants
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[], java.util.List<byte[]>, org.bouncycastle.cert.plants.MerkleTreeHash)andverifySubtreeInclusionProof(long, long, long, byte[], byte[], java.util.List<byte[]>, org.bouncycastle.cert.plants.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[], java.util.List<byte[]>, org.bouncycastle.cert.plants.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:
-