def run():
    """Fetch the proof for the supplied certificate."""
    #TODO(eranm): Attempt fetching the SCT for this chain if none was given.
    if FLAGS.sct:
        cert_sct = client_pb2.SignedCertificateTimestamp()
        sct_data = open(FLAGS.sct, 'rb').read()
        if FLAGS.binary_sct:
            tls_message.decode(sct_data, cert_sct)
        else:
            cert_sct.ParseFromString(sct_data)
        sct_timestamp = cert_sct.timestamp
        print 'SCT for cert:', cert_sct
    else:
        sct_timestamp = FLAGS.timestamp

    constructed_leaf = construct_leaf_from_file(FLAGS.cert, sct_timestamp)
    leaf_hash = merkle.TreeHasher().hash_leaf(constructed_leaf)
    if FLAGS.verbose:
        print "Leaf hash: %s" % (leaf_hash.encode("hex"))

    (sth, proof) = fetch_single_proof(leaf_hash, FLAGS.log_url)
    if FLAGS.verbose:
        print "Leaf index in tree is %d, proof has %d hashes" % (
            proof.leaf_index, len(proof.audit_path))
        print "Audit path: %s" % ([t.encode('hex') for t in proof.audit_path])

    verifier = merkle.MerkleVerifier()
    if verifier.verify_leaf_inclusion(constructed_leaf, proof.leaf_index,
                                      proof.audit_path, sth):
        print 'Proof verifies OK.'
 def test_verify_leaf_inclusion_single_node_in_tree(self):
     # If there is only one entry in the tree, the tree root hash should be
     # equal to the leaf hash.
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     sth = self.STH(self.leaf_hash, 1)
     self.assertTrue(
         verifier.verify_leaf_inclusion(self.raw_hex_leaf, 0, [], sth))
 def test_verify_leaf_inclusion_good_proof(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     sth = self.STH(self.expected_root_hash, self.tree_size)
     self.assertTrue(
         verifier.verify_leaf_inclusion(
             self.raw_hex_leaf, self.leaf_index, self.sha256_audit_path,
             sth))
 def test_verify_leaf_inclusion_bad_proof(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     # Expect this test to fail by providing an incorrect root hash.
     sth = self.STH(self.zeros, self.tree_size)
     self.assertRaises(
         error.ProofError, verifier.verify_leaf_inclusion,
         self.raw_hex_leaf, self.leaf_index, self.sha256_audit_path, sth)
 def test_verify_leaf_inclusion_all_nodes_all_tree_sizes_up_to_4(self):
     leaves = ["aa", "bb", "cc", "dd"]
     hh = HexTreeHasher()
     leaf_hashes = [hh.hash_leaf(l) for l in leaves]
     hc = hh.hash_children
     proofs_per_tree_size = {
         1: [[] ],
         2: [[leaf_hashes[1]], [leaf_hashes[0]]],
         3: [[leaf_hashes[1], leaf_hashes[2]], # leaf 0
             [leaf_hashes[0], leaf_hashes[2]], # leaf 1
             [hc(leaf_hashes[0], leaf_hashes[1])]], # leaf 2
         4: [[leaf_hashes[1], hc(leaf_hashes[2], leaf_hashes[3])], # leaf 0
             [leaf_hashes[0], hc(leaf_hashes[2], leaf_hashes[3])], # leaf 1
             [leaf_hashes[3], hc(leaf_hashes[0], leaf_hashes[1])], # leaf 2
             [leaf_hashes[2], hc(leaf_hashes[0], leaf_hashes[1])], # leaf 3
             ]
         }
     tree = merkle.CompactMerkleTree(hasher=HexTreeHasher())
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     # Increase the tree by one leaf each time
     for i in range(4):
         tree.append(leaves[i])
         tree_size = i + 1
         # ... and check inclusion proof validates for each node
         # of the tree
         for j in range(tree_size):
           proof = proofs_per_tree_size[tree_size][j]
           sth = self.STH(tree.root_hash(), tree_size)
           self.assertTrue(
               verifier.verify_leaf_inclusion(
                   leaves[j], j, proof, sth))
 def test_calculate_root_hash_good_proof(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     self.assertEqual(
         verifier._calculate_root_hash_from_audit_path(
             self.leaf_hash, self.leaf_index, self.sha256_audit_path[:],
             self.tree_size),
         self.expected_root_hash)
 def test_verify_leaf_inclusion_throws_on_bad_indices(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     sth = self.STH("", 6)
     self.assertRaises(ValueError,
         verifier.verify_leaf_inclusion, "", -3, [], sth)
     negative_sth = self.STH("", -3)
     self.assertRaises(ValueError,
         verifier.verify_leaf_inclusion, "", 3, [], negative_sth)
 def test_verify_tree_consistency_proof_too_short(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     self.assertRaises(
         error.ProofError, verifier.verify_tree_consistency, 6, 8,
         "76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef",
         "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328",
         ["0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a",
          "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0"]
         )
 def test_verify_tree_consistency_newer_tree_is_smaller(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     self.assertRaises(
         ValueError, verifier.verify_tree_consistency, 5, 2,
         "4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4",
         "fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125",
         ["5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e",
          "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b"]
         )
 def test_verify_tree_consistency_always_accepts_empty_tree(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     # Give some bogus proof too; it should be ignored.
     self.assertTrue(verifier.verify_tree_consistency(
         0, 1,
         "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
         "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
         ["6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"]
         ))
 def test_calculate_root_too_short_proof(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     leaf_index = self.leaf_index + int(
         math.pow(2, len(self.sha256_audit_path) + 1))
     self.assertRaises(
         error.ProofError,
         verifier._calculate_root_hash_from_audit_path,
         self.leaf_hash, leaf_index, self.sha256_audit_path[:],
         self.tree_size)
 def __init__(self, key_info, merkle_verifier=merkle.MerkleVerifier()):
     """Initialize from KeyInfo protocol buffer and a MerkleVerifier."""
     self.__merkle_verifier = merkle_verifier
     if (key_info.type == client_pb2.KeyInfo.ECDSA):
         self.__sig_verifier = verify_ecdsa.EcdsaVerifier(key_info)
     elif (key_info.type == client_pb2.KeyInfo.RSA):
         self.__sig_verifier = verify_rsa.RsaVerifier(key_info)
     else:
         raise error.UnsupportedAlgorithmError("Key type %d not supported" %
                                               key_info.type)
 def test_verify_leaf_inclusion_incorrect_length_proof(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     sth = self.STH(self.zeros, 4)
     # Too long a proof
     self.assertRaises(error.ProofError, verifier.verify_leaf_inclusion,
                       self.ones, 0, [self.zeros, self.zeros, self.zeros],
                       sth)
     # Too short a proof
     self.assertRaises(error.ProofError, verifier.verify_leaf_inclusion,
                       self.ones, 0, [self.zeros], sth)
 def test_verify_tree_consistency_bad_first_hash(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     # A bit has been flipped in the first hash.
     self.assertRaises(
         error.ConsistencyError, verifier.verify_tree_consistency, 6, 8,
         "76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ee",
         "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328",
         ["0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a",
          "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0",
          "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"]
         )
 def test_verify_leaf_inclusion_rightmost_node_in_unbalanced_odd_tree(
     self):
     # Show that verify_leaf_inclusion works when required to check a proof
     # for the right-most, even-indexed node: In a tree of 5 nodes, ask for
     # inclusion proof check for leaf 4 (the 5th).
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     hh = HexTreeHasher()
     h_s1 = hh.hash_leaf(self.ones)
     h_root = hh.hash_children(self.zeros, h_s1)
     sth = self.STH(h_root, 5)
     self.assertTrue(
         verifier.verify_leaf_inclusion(self.ones, 4, [self.zeros, ], sth))
Пример #16
0
    def __init__(self, key_info, merkle_verifier=merkle.MerkleVerifier()):
        """Initialize from KeyInfo protocol buffer and a MerkleVerifier."""
        self.__merkle_verifier = merkle_verifier
        if key_info.type != client_pb2.KeyInfo.ECDSA:
            raise error.UnsupportedAlgorithmError("Key type %d not supported" %
                                                  key_info.type)

        # Will raise a PemError on invalid encoding
        self.__der, _ = pem.from_pem(key_info.pem_key,
                                     LogVerifier.__ECDSA_READ_MARKERS)
        try:
            self.__pubkey = ecdsa.VerifyingKey.from_der(self.__der)
        except ecdsa.der.UnexpectedDER as e:
            raise error.EncodingError(e)
 def test_verify_leaf_inclusion_rightmost_node_in_tree(self):
     # Show that verify_leaf_inclusion works when required to check a proof
     # for the right-most node: In a tree of 8 nodes, ask for inclusion
     # proof check for leaf 7.
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     hh = HexTreeHasher()
     h_s1 = hh.hash_leaf(self.ones)
     h_c3 = hh.hash_children(self.zeros, h_s1)
     h_c2 = hh.hash_children(self.zeros, h_c3)
     h_root = hh.hash_children(self.zeros, h_c2)
     sth = self.STH(h_root, 8)
     self.assertTrue(
         verifier.verify_leaf_inclusion(
             self.ones, 7, [self.zeros, self.zeros, self.zeros], sth))
    def test_verify_tree_consistency_for_equal_tree_sizes(self):
        verifier = merkle.MerkleVerifier(HexTreeHasher())
        # Equal tree sizes and hashes, and a bogus proof that should be ignored.
        self.assertTrue(verifier.verify_tree_consistency(
            3, 3,
            "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
            "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
            ["6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"]
            ))

        # Equal tree sizes but different hashes.
        self.assertRaises(
            error.ConsistencyError, verifier.verify_tree_consistency, 3, 3,
            "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01e",
            "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
            [])
Пример #19
0
    def __init__(self,
                 ct_logs,
                 db,
                 cert_db,
                 temp_db_factory,
                 monitor_state_dir,
                 agent=None,
                 state_keeper_class=None):
        """Initialize from a CtLogs proto."""
        threading.Thread.__init__(self)

        self.__monitors = []
        self.__db = db
        if not agent:
            agent = twisted_client.Agent(reactor)
        if not state_keeper_class:
            state_keeper_class = state.StateKeeper

        for log in ct_logs.ctlog:
            if not log.log_server or not log.log_id or not log.public_key_info:
                raise RuntimeError("Cannot start monitor: log proto has "
                                   "missing or empty fields: %s" % log)

            try:
                temp_db = temp_db_factory.create_storage(log.log_server)
                client = async_log_client.AsyncLogClient(
                    agent, log.log_server, temp_db)
                hasher = merkle.TreeHasher()
                verifier = verify.LogVerifier(log.public_key_info,
                                              merkle.MerkleVerifier(hasher))
                # Convert from standard Base64 to URL-safe Base64 so that the
                # log ID can be used as part of a file path.
                log_id_urlsafe = log.log_id.replace('/', '_').replace('+', '-')
                state_keeper = state_keeper_class(monitor_state_dir + "/" +
                                                  log_id_urlsafe)
                log_key = db.get_log_id(log.log_server)
                self.__monitors.append(
                    monitor.Monitor(client, verifier, hasher, db, cert_db,
                                    log_key, state_keeper))
            except:
                logging.error("Error starting monitor for log: %s" % log)
                raise

        self.__last_update_start_time = 0
        self.__stopped = False
        self.__called_later = None
    def test_tree_consistency_proof_generated(self):
        """Test consistency proof generation.

        Consistency proof generation correctness test for generated proofs.
        """
        leaves = []
        for i in range(128):
            leaves.append(chr(i) * 32)

        tree = in_memory_merkle_tree.InMemoryMerkleTree(leaves)
        verifier = merkle.MerkleVerifier()

        for i in range(1, tree.tree_size()):
            for j in range(i):
                consistency_proof = tree.get_consistency_proof(j, i)
                self.assertTrue(verifier.verify_tree_consistency(
                        j, i, tree.get_root_hash(j), tree.get_root_hash(i),
                        consistency_proof))
    def test_tree_inclusion_proof_generated(self):
        """Test inclusion proof generation.

        Test inclusion proof generation correctness for generated proofs.
        """
        leaves = []
        leaf_hashes = []
        hasher = merkle.TreeHasher()
        for i in range(128):
            leaves.append(chr(i) * 32)
            leaf_hashes.append(hasher.hash_leaf(leaves[-1]))

        tree = in_memory_merkle_tree.InMemoryMerkleTree(leaves)
        verifier = merkle.MerkleVerifier()

        for i in range(1, tree.tree_size()):
            for j in range(i):
                audit_path = tree.get_inclusion_proof(j, i)
                dummy_sth = DummySTH(i, tree.get_root_hash(i))
                verifier.verify_leaf_hash_inclusion(
                        leaf_hashes[j], j, audit_path, dummy_sth)
    def test_tree_inclusion_proof_precomputed(self):
        """Test inclusion proof generation.

        Test inclusion proof generation correctness test for known-good
        proofs.
        """
        tree = in_memory_merkle_tree.InMemoryMerkleTree(TEST_VECTOR_DATA)
        verifier = merkle.MerkleVerifier()
        for v in PRECOMPUTED_PATH_TEST_VECTORS:
            audit_path = tree.get_inclusion_proof(v.leaf, v.tree_size_snapshot)
            self.assertEqual(len(audit_path), v.path_length)
            self.assertEqual(audit_path, v.path)

            leaf_data = TEST_VECTOR_DATA[v.leaf]
            leaf_hash = merkle.TreeHasher().hash_leaf(leaf_data)
            dummy_sth = DummySTH(v.tree_size_snapshot,
                tree.get_root_hash(v.tree_size_snapshot))

            if v.tree_size_snapshot > 0:
                verifier.verify_leaf_hash_inclusion(
                        leaf_hash, v.leaf, audit_path, dummy_sth)
Пример #23
0
    def __init__(self, ct_logs, db, temp_db_factory, monitor_state_dir):
        """Initialize from a CtLogs proto."""
        threading.Thread.__init__(self)

        self.__monitors = []
        self.__db = db
        for log in ct_logs.ctlog:
            if not log.log_server or not log.log_id or not log.public_key_info:
                raise RuntimeError("Cannot start monitor: log proto has "
                                   "missing or empty fields: %s" % log)
            client = log_client.LogClient(log.log_server)
            hasher = merkle.TreeHasher()
            verifier = verify.LogVerifier(log.public_key_info,
                                          merkle.MerkleVerifier(hasher))
            state_keeper = state.StateKeeper(FLAGS.monitor_state_dir + "/" +
                                             log.log_id)
            temp_db = temp_db_factory.create_storage(log.log_server)
            self.__monitors.append(
                monitor.Monitor(client, verifier, hasher, db, temp_db,
                                state_keeper))

        self.__last_update_start_time = 0
        self.__stopped = False
    leaf_input = j['entries'][0]['leaf_input']
    logging.info('leaf = %s', leaf_input)
    leaf = base64.b64decode(leaf_input)
    leaf_hash = hashlib.sha256(chr(0) + leaf).digest()

    keyinfo = client_pb2.KeyInfo()
    keyinfo.type = keyinfo.ECDSA
    keyinfo.pem_key = keypem
    log_verifier = verify.LogVerifier(keyinfo)

    lookup = CTDNSLookup(logdns, log_verifier)
    sth = lookup.GetSTH()
    logging.info('sth = %s', sth)

    logging.info('hash = %s', base64.b64encode(leaf_hash))
    verifier = merkle.MerkleVerifier()
    index = int(index)
    audit_path = []
    prev = None
    apl = verifier.audit_path_length(index, sth.tree_size)
    for level in range(0, apl):
        h = lookup.GetEntry(level, index, sth.tree_size)
        logging.info('hash = %s', base64.b64encode(h))
        audit_path.append(h[:32])

        if prev:
            if level < apl - 6:
                assert prev[32:] == h[:-32]
            else:
                assert prev[32:] == h
        else:
 def setUp(self):
     self.verifier = merkle.MerkleVerifier(HexTreeHasher())
     self.STH = namedtuple("STH", ["sha256_root_hash", "tree_size"])
     self.ones = "11" * 32
     self.zeros = "00" * 32
 def test_verify_tree_consistency(self):
     verifier = merkle.MerkleVerifier(HexTreeHasher())
     for test_vector in  MerkleVerifierTest.sha256_proofs:
         self.assertTrue(verifier.verify_tree_consistency(*test_vector))