TreeUtil.hash_tree

Calculate root hash of a L-tree or a binary tree. The number of leaves is not required to be a power of 2.

template TreeUtil(alias hash_2n_n, H, M)
@safe @nogc pure nothrow
H
hash_tree
(
uint len
)
(
in H[] leaves
,
in M[] masks
)
if (
len > 0
)
in { assert (leaves.length == len); assert (1 << masks.length >= leaves.length, "Not enough bitmasks."); }
if (
is_hash_2n_n!(hash_2n_n, H) &&
2 * H.length == M.length
)

Parameters

len

Number of leaves. Must be larger than 0.

leaves
Type: H[]

The leaves of the tree. Exactly l.

masks
Type: M[]

One bitmask for each layer of the tree.

Examples

L-tree hash sanity test.

1 t {
2 		import dcrypt.pqc.sphincs.sphincs256: hash_2n_n;
3 
4 		enum l = 3;
5 		enum hash_bytes = 32;
6 		alias ubyte[hash_bytes] hash256;
7 		alias TreeUtil!(hash_2n_n, ubyte[hash_bytes], ubyte[2*hash_bytes]) Tree;
8 		hash256[l] leaves;
9 		for(uint i = 0; i < l; ++i) { leaves[i][] = cast(ubyte) (i+1); } // Make leaves distinct.
10 		
11 		ubyte[64][2] masks;
12 		masks[0][] = 1;
13 		masks[1][] = 2;
14 		
15 		hash256 root = Tree.hash_tree!l(leaves, masks);
16 		
17 		leaves[0][] ^= masks[0][0..hash_bytes];
18 		leaves[1][] ^= masks[0][hash_bytes..$];
19 		
20 		hash256 root2 = hash_2n_n(leaves[0], leaves[1]);
21 		
22 		root2[] ^= masks[1][0..hash_bytes];
23 		leaves[2][] ^= masks[1][hash_bytes..$];
24 		
25 		root2 = hash_2n_n(root2, leaves[2]);
26 		assert(root == root2)

Test hash_ltree against result of reference implementation (l_tree()).

1 t {
2 
3 		import dcrypt.pqc.sphincs.sphincs256: hash_2n_n, hash256;
4 
5 		enum l = 67;
6 		enum hash_bytes = 32;
7 		alias TreeUtil!(hash_2n_n, ubyte[hash_bytes], ubyte[2*hash_bytes]) Tree;
8 		
9 		hash256[l] leaves;
10 		for(uint i = 0; i < leaves.length; ++i) {
11 			leaves[i] = cast(ubyte) i;
12 		}
13 		
14 		ubyte[2*hash_bytes][7] masks;
15 		
16 		for(uint i = 0; i < masks.length; ++i) { 
17 			masks[i][0..hash_bytes] = cast(ubyte) (1+2*i);
18 			masks[i][hash_bytes..$] = cast(ubyte) (2+2*i);
19 		}
20 		
21 		hash256 root = Tree.hash_tree!l(leaves, masks);
22 		
23 		assert(root == x"59641ed4970735d4e1d84ec00e4780d1ab211ebd9339b9962de2a15ead43e1e4", "hash_ltree() failed.")

Meta