Number of leaves. Must be larger than 0.
The leaves of the tree. Exactly l.
One bitmask for each layer of the tree.
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.")
Calculate root hash of a L-tree or a binary tree. The number of leaves is not required to be a power of 2.