Exemple #1
0
        public async Task <bool> CheckConsistency(long logId, LogRootV1 first, LogRootV1 second)
        {
            var resp = await client.GetConsistencyProofAsync(new GetConsistencyProofRequest
            {
                LogId          = logId,
                FirstTreeSize  = (Int64)first.TreeSize,
                SecondTreeSize = (Int64)second.TreeSize,
            });

            return(Verifier.VerifyConsistencyProof(first, second, resp.Proof));
        }
Exemple #2
0
        private LogRootV1 ParseLogRootV1(BinaryReader reader)
        {
            LogRootV1 logRoot = new LogRootV1();

            logRoot.TreeSize = reader.ReadUInt64();
            int rootHashLen = reader.ReadByte();

            logRoot.RootHash       = reader.ReadBytes(rootHashLen);
            logRoot.TimestampNanos = reader.ReadUInt64();
            logRoot.Revision       = reader.ReadUInt64();
            int metadataLen = reader.ReadUInt16();

            logRoot.Metadata = reader.ReadBytes(metadataLen);
            return(logRoot);
        }
Exemple #3
0
        public static bool VerifyConsistencyProof(LogRootV1 first, LogRootV1 second, Trillian.Proof proof)
        {
            if (first.TreeSize == second.TreeSize)
            {
                if (proof.Hashes.Count > 0)
                {
                    throw new ArgumentException("first.TreeSize == second.TreeSize but proof.Hashes.Count > 0");
                }
                return(first.RootHash.Equals(second.RootHash));
            }
            if (first.TreeSize < second.TreeSize)
            {
                throw new ArgumentException("first.TreeSize < second.TreeSize");
            }

            using SHA256 hasher = SHA256.Create();

            // 1.  If "first" is an exact power of 2, then prepend "first_hash" to
            //     the "consistency_path" array.
            if (IsPowerOf2(first.TreeSize))
            {
                proof.Hashes.Insert(0, Google.Protobuf.ByteString.CopyFrom(first.RootHash));
            }

            // 2.  Set "fn" to "first - 1" and "sn" to "second - 1".
            UInt64 fn = first.TreeSize - 1;
            UInt64 sn = second.TreeSize - 1;

            // 3.  If "LSB(fn)" is set, then right-shift both "fn" and "sn" equally
            //     until "LSB(fn)" is not set.
            while ((fn & 1) == 1)
            {
                fn >>= 1;
                sn >>= 1;
            }

            // 4.  Set both "fr" and "sr" to the first value in the
            //     "consistency_path" array.
            var fr = proof.Hashes[0].ToByteArray();
            var sr = proof.Hashes[0].ToByteArray();

            // 5.  For each subsequent value "c" in the "consistency_path" array:
            foreach (var c in proof.Hashes)
            {
                // If "sn" is 0, stop the iteration and fail the proof verification.
                if (sn == 0)
                {
                    return(false);
                }
                // If "LSB(fn)" is set, or if "fn" is equal to "sn", then:
                if ((fn & 1) == 1 || fn == sn)
                {
                    // 1.  Set "fr" to "HASH(0x01 || c || fr)"
                    //     Set "sr" to "HASH(0x01 || c || sr)"
                    MemoryStream memStream = new MemoryStream(1 + c.Length + fr.Length);
                    memStream.WriteByte(0x01);
                    memStream.Write(c.Span);
                    memStream.Write(fr);
                    memStream.Seek(0, SeekOrigin.Begin);
                    fr = hasher.ComputeHash(memStream);

                    memStream.Seek(1 + c.Length, SeekOrigin.Begin);
                    memStream.Write(sr);
                    memStream.Seek(0, SeekOrigin.Begin);
                    sr = hasher.ComputeHash(memStream);

                    // 2. If "LSB(fn)" is not set, then right-shift both "fn" and "sn"
                    //    equally until either "LSB(fn)" is set or "fn" is "0".
                    while ((fn & 1) == 0)
                    {
                        fn >>= 1;
                        sn >>= 1;
                        if (fn == 0)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    // Otherwise:
                    // 1.Set "sr" to "HASH(0x01 || sr || c)"
                    MemoryStream memStream = new MemoryStream(1 + c.Length + fr.Length);
                    memStream.WriteByte(0x01);
                    memStream.Write(sr);
                    memStream.Write(c.Span);
                    memStream.Seek(0, SeekOrigin.Begin);
                    sr = hasher.ComputeHash(memStream);
                }
                // Finally, right - shift both "fn" and "sn" one time.
                fn >>= 1;
                sn >>= 1;
            }
            // 6.  After completing iterating through the "consistency_path" array
            //     as described above, verify that the "fr" calculated is equal to
            //     the "first_hash" supplied, that the "sr" calculated is equal to
            //     the "second_hash" supplied and that "sn" is 0.
            return(fr.Equals(first.RootHash) && sr.Equals(second.RootHash) && sn == 0);
        }