Skip to content

Commit 83d0f81

Browse files
committed
docs: update Merkle tree documentation for v3.0 and blockchain attestation
Major updates to Merkle tree documentation to reflect v3.0 improvements and blockchain attestation features: - Update README.md: - Clarify Merkle tree as "Merkle-Inspired Hash Set" optimized for small records - Add v3.0 security improvements and interoperability features - Add new section on blockchain attestation and verification flow - Update usage examples to use MerkleTreeVersionStrings.V3_0 - Update selective-disclosure.md: - Add detailed v3.0 security improvements section - Add security guarantees and processing requirements - Add blockchain attestation section with process and properties - Update examples to use v3.0 format and features - Enhance verification section with v3.0 specifics - Update MerkleTree.cs: - Add comprehensive documentation for v3.0 features - Document security improvements and interoperability features - Add use cases section These changes better reflect the security and interoperability improvements in v3.0, particularly around the protected header leaf and blockchain attestation capabilities.
1 parent 171023d commit 83d0f81

File tree

3 files changed

+183
-13
lines changed

3 files changed

+183
-13
lines changed

docs/merkle/README.md

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ Documentation on our approach to selective disclosure in Merkle trees, allowing
1010

1111
## Key Features
1212

13-
- **Standard Merkle Tree Implementation**: Binary tree of hashes with efficient verification
13+
- **Merkle-Inspired Hash Set**: Optimized for small records (less than 20 items) where most data will be revealed
1414
- **Automatic Random Salts**: Each leaf gets its own cryptographically secure random salt by default
1515
- **Selective Disclosure**: Ability to reveal only specific leaves while maintaining verifiability
1616
- **Flexible Serialization**: JSON representation with options for privacy and null handling
1717
- **Clean API Design**: Intuitive interfaces for creating, modifying, and verifying trees
18+
- **Version 3.0 Support**: Enhanced security with protected header leaf and JOSE-inspired format
1819

1920
## Security Best Practices
2021

@@ -23,6 +24,10 @@ For optimal security, we've designed our Merkle tree implementation with these b
2324
- **Unique Random Salts**: Each leaf in the tree automatically gets its own secure random salt
2425
- **Salt Length**: 16 bytes (128 bits) of randomness by default
2526
- **Correlation Protection**: Different salt for each leaf prevents correlation attacks on identical data
27+
- **Protected Header**: First leaf contains cryptographically protected metadata (algorithm, leaf count, document type)
28+
- **Minimum Leaf Count**: All valid trees must have at least two leaves to prevent single-leaf attacks
29+
- **Algorithm Protection**: Hash algorithm is cryptographically bound to the tree structure
30+
- **Document Type Safety**: Exchange field prevents mixing different types of records
2631

2732
## Implementation Details
2833

@@ -32,11 +37,33 @@ The Merkle tree implementation is available in the `Evoq.Blockchain.Merkle` name
3237
- `MerkleLeaf`: Represents a leaf node in the tree, containing data, salt, hash, and content type
3338
- `MerkleMetadata`: Contains metadata about the tree, such as version and hash algorithm
3439

40+
## Version 3.0 Improvements
41+
42+
Version 3.0 introduces significant security enhancements:
43+
44+
1. **Security Improvements**:
45+
- Protected header leaf with cryptographically secured metadata
46+
- Prevention of single leaf, leaf addition/removal, and algorithm substitution attacks
47+
- Document type safety through the exchange field
48+
- Strict validation of header leaf and tree structure
49+
50+
2. **Interoperability Features**:
51+
- JOSE-inspired header format (alg, typ fields)
52+
- Standard MIME types for structured data exchange
53+
- Support for selective disclosure through private leaves
54+
- Efficient proof generation with O(log n) hashes
55+
56+
3. **Use Cases**:
57+
- Selective Disclosure: Reveal specific leaves while keeping others private
58+
- Document Exchange: Exchange structured data with type safety and integrity
59+
- Proof Generation: Generate compact proofs for verification
60+
- Private Storage: Store full structure for quick proof reissuance
61+
3562
## Usage
3663

3764
```csharp
38-
// Create a new tree
39-
var tree = new MerkleTree();
65+
// Create a new v3.0 tree
66+
var tree = new MerkleTree(MerkleTreeVersionStrings.V3_0);
4067

4168
// Add JSON key-value pairs with automatic random salts (preferred)
4269
var data = new Dictionary<string, object?> { { "key1", "value1" }, { "key2", 123 } };
@@ -49,6 +76,30 @@ tree.RecomputeSha256Root();
4976
bool isValid = tree.VerifySha256Root();
5077
```
5178

79+
## Blockchain Attestation
80+
81+
The Merkle tree implementation is designed to work seamlessly with blockchain attestations:
82+
83+
1. **Root Hash Attestation**: The root hash of a Merkle tree can be attested on a blockchain, providing a tamper-proof record of the tree's state at a specific point in time.
84+
85+
2. **Verification Flow**:
86+
- A Merkle tree is created and its root hash is attested on the blockchain
87+
- The complete tree can be shared with users or stored privately
88+
- When verification is needed, the tree is parsed from JSON
89+
- The parsed tree's root is verified against the attested hash on the blockchain
90+
91+
3. **Selective Disclosure with Attestation**:
92+
- Users can create selectively disclosed versions of the tree
93+
- The disclosed tree maintains the same root hash
94+
- Verifiers can confirm the disclosed tree matches the attested root
95+
96+
This pattern is particularly valuable for:
97+
- Digital identity documents
98+
- Credential verification
99+
- Document attestation
100+
- Supply chain tracking
101+
- Any scenario requiring both privacy and verifiability
102+
52103
For a complete usage example, see the [Complete Example section in the Selective Disclosure documentation](./selective-disclosure.md#complete-example-digital-passport).
53104

54105
For more detailed implementation information, examine the source code in:

docs/merkle/selective-disclosure.md

Lines changed: 104 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,69 @@ In many verification scenarios, you need to prove only specific attributes (like
2121

2222
Traditional approaches require either:
2323
1. Revealing the entire document (compromising privacy)
24-
2. Creating separate trees for each attribute (sacrificing the unified cryptographic binding)
25-
3. Implementing complex zero-knowledge proofs (adding significant complexity)
24+
1. Creating separate trees for each attribute (sacrificing the unified cryptographic binding)
25+
1. Implementing complex zero-knowledge proofs (adding significant complexity)
2626

2727
Our implementation provides a clean, elegant solution to this problem through a technique we call "private leaves" - leaves whose content is withheld while their cryptographic presence is maintained.
2828

29+
## Version 3.0 Security Improvements
30+
31+
Version 3.0 introduces a protected header leaf that significantly enhances security by preventing several critical attacks:
32+
33+
1. **Single Leaf Attack Prevention**
34+
- The header leaf forces all valid trees to have at least two leaves
35+
- This prevents an attacker from creating a single-leaf tree that matches a known root hash
36+
- The header leaf must be valid JSON, making it harder to fake
37+
38+
2. **Leaf Count Protection**
39+
- The header leaf contains the exact number of leaves expected
40+
- This prevents attackers from adding or removing leaves to find hash collisions
41+
- The leaf count is cryptographically protected by being part of the tree structure
42+
43+
3. **Algorithm Protection**
44+
- The hash algorithm is included in the protected header leaf
45+
- This prevents attackers from switching to weaker algorithms
46+
- The algorithm choice is cryptographically bound to the tree structure
47+
48+
4. **Document Type Safety**
49+
- The `exchange` field specifies the type of document (e.g., "passport", "invoice")
50+
- This prevents mixing different types of records in the same tree
51+
- Helps prevent attacks where a proof of one document type is used as another
52+
53+
5. **Metadata Protection**
54+
- All critical metadata is stored in the first leaf of the tree
55+
- This metadata is cryptographically protected by the tree's structure
56+
- Makes it impossible to modify metadata without breaking the tree's integrity
57+
58+
### Security Guarantees
59+
60+
The v3.0 design provides security through two difficult problems for attackers:
61+
62+
1. **Finding Private Leaf Hashes**
63+
- Attackers must find correct hash values for private leaves
64+
- These hashes must combine to produce the known root hash
65+
- This is computationally infeasible due to the cryptographic properties of the hash function
66+
67+
2. **Finding Data/Salt Combinations**
68+
- Attackers must find data and salt combinations that either:
69+
- Produce the original hash for a leaf
70+
- Or produce a different hash that still solves for the root hash
71+
- This is prevented by the use of cryptographically secure random salts
72+
73+
### Processing Requirements
74+
75+
When processing v3.0 trees, verifiers must:
76+
77+
1. Ensure there are at least two leaf nodes
78+
2. Verify the first leaf contains valid JSON metadata
79+
3. Validate the algorithm is known, supported, and secure
80+
4. Confirm the leaf count matches the actual number of leaves
81+
5. Verify all leaf hashes can be recomputed from their data and salt
82+
6. Validate data formats and content (e.g., postal codes, dates)
83+
7. Challenge users to provide details from the original document
84+
85+
This comprehensive validation ensures the tree's integrity and prevents various attacks while maintaining the efficiency of selective disclosure.
86+
2987
## Important: Security Through Unique Salts
3088

3189
> **SECURITY BEST PRACTICE**: Each leaf in a Merkle tree should have its own unique random salt.
@@ -41,6 +99,7 @@ We've implemented a simple yet powerful solution that enables any subset of leav
4199
2. **Clean Serialization**: Private leaves contain only their hash, omitting data, salt, and content type
42100
3. **Seamless Verification**: Standard verification algorithms still work with private leaves
43101
4. **Flexible Privacy Control**: Any combination of leaves can be made private or public
102+
5. **Efficient Proofs**: Generates compact proofs with O(log n) hashes for verification
44103

45104
## Implementation Details
46105

@@ -95,6 +154,31 @@ This selective disclosure approach is particularly valuable for:
95154
2. **Credential Validation**: Verify qualifications without exposing all credential details
96155
3. **Document Attestation**: Cryptographically verify specific document attributes
97156
4. **Blockchain Applications**: Reduce on-chain data while maintaining verifiability
157+
5. **Private Storage**: Store full structure (data, salts, hashes) for quick proof reissuance
158+
159+
## Blockchain Attestation
160+
161+
The selective disclosure implementation is designed to work seamlessly with blockchain attestations:
162+
163+
1. **Attestation Process**:
164+
- Create a Merkle tree with all required data
165+
- Compute and verify the root hash
166+
- Attest the root hash on the blockchain
167+
- Store or share the complete tree with users
168+
169+
2. **Verification Process**:
170+
- Parse the selectively disclosed tree from JSON
171+
- Verify the tree's structure and integrity
172+
- Compare the tree's root hash with the attested hash on the blockchain
173+
- Validate the disclosed data against the attested root
174+
175+
3. **Security Properties**:
176+
- The attested root hash provides a tamper-proof record
177+
- Selective disclosure maintains the same root hash
178+
- The header leaf in v3.0 prevents various attacks
179+
- The verification process ensures data integrity
180+
181+
This pattern enables privacy-preserving verification while maintaining the security guarantees of blockchain attestation.
98182

99183
## Security Considerations
100184

@@ -125,6 +209,10 @@ Let's walk through a complete example of implementing selective disclosure with
125209
First, we'll create a Merkle tree containing various passport data fields:
126210

127211
```csharp
212+
// Create a v3.0 tree for the passport
213+
var merkleTree = new MerkleTree(MerkleTreeVersionStrings.V3_0);
214+
merkleTree.Metadata.ExchangeDocumentType = "passport";
215+
128216
// Passport data fields
129217
var passportData = new Dictionary<string, object?>
130218
{
@@ -160,8 +248,7 @@ var passportData = new Dictionary<string, object?>
160248
}
161249
};
162250

163-
// Create the Merkle tree and add all fields as leaves with automatically generated random salts
164-
var merkleTree = new MerkleTree();
251+
// Add all fields as leaves with automatically generated random salts
165252
merkleTree.AddJsonLeaves(passportData); // Uses random salts automatically
166253
167254
// Compute the root hash
@@ -241,16 +328,17 @@ The resulting JSON would look like this, with private fields only showing their
241328
}
242329
],
243330
"root": "0x42b0557fd2578668da8218367ef9f8f0e233a2a928a979f66c8331fda5d81af8",
244-
"metadata": {
245-
"hashAlgorithm": "sha256",
246-
"version": "1.0"
331+
"header": {
332+
"typ": "application/merkle-exchange-3.0+json"
247333
}
248334
}
249335
```
250336

337+
Note that in v3.0, the header leaf (first leaf) contains protected metadata about the tree, including the hash algorithm, leaf count, and document type. This metadata is cryptographically protected by the tree's structure, preventing tampering with critical tree parameters.
338+
251339
### Verifying a Tree with Private Leaves
252340

253-
The verification process works the same way with private leaves:
341+
The verification process works the same way with private leaves, but with enhanced security in v3.0:
254342

255343
```csharp
256344
// Parse the selectively disclosed JSON
@@ -260,7 +348,11 @@ var parsedTree = MerkleTree.Parse(jsonWithPrivacy);
260348
bool isStillValid = parsedTree.VerifySha256Root(); // Should be true
261349
```
262350

263-
The verification works because when a leaf is private (has no data or salt), the verification algorithm uses the provided hash directly.
351+
The verification works because:
352+
1. When a leaf is private (has no data or salt), the verification algorithm uses the provided hash directly
353+
2. In v3.0, the header leaf's metadata (algorithm, leaf count, document type) is verified as part of the tree structure
354+
3. The parser validates that the leaf count matches the actual number of leaves
355+
4. The hash algorithm specified in the header leaf is used for verification
264356

265357
### Creating a Proof for a Specific Claim
266358

@@ -289,7 +381,7 @@ There are two ways to create private leaves in a Merkle tree:
289381
1. **Using AddPrivateLeaf**: Create a leaf that is private from the start:
290382
```csharp
291383
// Create a tree with a private leaf
292-
var tree = new MerkleTree();
384+
var tree = new MerkleTree(MerkleTreeVersionStrings.V3_0);
293385
var hash = Hex.Parse("0x1234567890abcdef");
294386
var privateLeaf = tree.AddPrivateLeaf(hash);
295387
```
@@ -308,6 +400,7 @@ Both approaches result in leaves that:
308400
- Only contain their hash in the JSON output
309401
- Maintain the tree's verifiability
310402
- Preserve privacy of the leaf's data
403+
- In v3.0, are protected by the header leaf's metadata
311404

312405
## Conclusion
313406

@@ -319,5 +412,6 @@ The approach provides:
319412
2. Clean JSON representation with only the necessary data
320413
3. Maintained cryptographic verifiability
321414
4. Simple implementation using predicates
415+
5. Enhanced security through protected metadata in v3.0
322416

323417
This is particularly valuable for real-world applications where selective disclosure balances privacy with verifiability needs.

src/Evoq.Blockchain/Blockchain.Merkle/MerkleTree.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,31 @@ namespace Evoq.Blockchain.Merkle;
1515
/// A simple Merkle tree which can be assembled manually or parsed from a JSON string. The design forces the user
1616
/// to verify the root before serializing to JSON, ensuring that the tree is valid before it is saved or exchanged.
1717
/// If the tree fails verification, an exception can be caught and the tree root can be recomputed from the leaves.
18+
///
19+
/// Version 3.0 introduces a protected header leaf that provides enhanced security and interoperability:
20+
///
21+
/// Security Improvements:
22+
/// - The header leaf is part of the Merkle tree itself, making its contents (algorithm, leaf count, exchange type)
23+
/// cryptographically protected by the tree's structure
24+
/// - Protects against leaf addition/removal attacks by including the exact leaf count
25+
/// - Prevents single leaf attacks by requiring a header leaf
26+
/// - Protects against algorithm substitution by including the hash algorithm in the protected header
27+
/// - Includes the type of data/record being exchanged (e.g., "invoice", "contract", "certificate") to prevent
28+
/// mixing different types of records in the same tree
29+
/// - Uses proper MIME types for structured exchange format
30+
/// - Performs strict validation of the header leaf during parsing
31+
///
32+
/// Interoperability Features:
33+
/// - Uses standard MIME types (application/merkle-exchange-3.0+json) for structured data exchange
34+
/// - Supports selective disclosure through private leaves and makePrivate predicates
35+
/// - Enables efficient proof generation with O(log n) hashes for classical Merkle proofs
36+
/// - Maintains backward compatibility with v1.0 and v2.0 formats
37+
///
38+
/// Use Cases:
39+
/// - Selective Disclosure: Reveal specific leaves while keeping others private
40+
/// - Document Exchange: Exchange structured data with type safety and integrity
41+
/// - Proof Generation: Generate compact proofs for verification
42+
/// - Private Storage: Store full structure (data, salts, hashes) for quick proof reissuance
1843
/// </remarks>
1944
public class MerkleTree
2045
{

0 commit comments

Comments
 (0)