public bool VerifyContent(byte[] content, uint offset) { Throw.If(offset >= MaxDepthLeafCount, "Offset does not correspond to maximum depth leaf"); var hash = new Hash(CryptoExtensions.Sha256(content, 0, (uint)content.Length)); return(hash == _tree[offset]); }
// chunkSize must be a power of 2 public MerkleTree(byte[] content) { //Throw.If(content == null || content.Length < ChunkSize, "invalid content"); Throw.If(content == null, "invalid content"); var chunkCount = (uint)(content.Length / ChunkSize); if (chunkCount * ChunkSize < content.Length) { chunkCount++; } MaxDepthLeafCount = NextPowerOf2(chunkCount); //int maxLevel = 1; var temp = MaxDepthLeafCount; uint nodeCount = 0; while (temp > 0) { nodeCount += temp; temp /= 2; //maxLevel++; } _tree = new Hash[nodeCount]; //hash the maximum depth leaves of the tree for (int i = 0; i < MaxDepthLeafCount; i++) { Hash hash; var ofs = (uint)(i * ChunkSize); if (ofs < content.Length) { var length = ChunkSize; if (ofs + length > content.Length) { length = (uint)(content.Length - ofs); } hash = new Hash(CryptoExtensions.Sha256(content, ofs, length)); } else { hash = Hash.Null; } _tree[i] = hash; } //and how combine the leaf hashes in the branches uint prevOffset = 0; uint prevRows = MaxDepthLeafCount; while (true) { uint rows = prevRows / 2; if (rows <= 0) { break; } uint offset = prevOffset + prevRows; for (uint i = 0; i < rows; i++) { uint childIndex = prevOffset + (i * 2); var left = _tree[childIndex]; var right = _tree[childIndex + 1]; _tree[offset + i] = Hash.MerkleCombine(left, right); } prevOffset = offset; prevRows = rows; } }
public static Hash CalculateBlockHash(byte[] content) { var hash = new Hash(CryptoExtensions.Sha256(content, 0, (uint)content.Length)); return(hash); }
public static Hash FromString(string str) { var bytes = CryptoExtensions.Sha256(str); return(new Hash(bytes)); }