def __init__(self, client, verifier, hasher, db, cert_db, log_key, state_keeper): self.__client = client self.__verifier = verifier self.__hasher = hasher self.__db = db self.__state_keeper = state_keeper # TODO(ekasper): once consistency checks are in place, also load/store # Merkle tree info. # Depends on: Merkle trees implemented in Python. self.__state = client_pb2.MonitorState() self.__report = aggregated_reporter.AggregatedCertificateReport( (text_reporter.TextCertificateReport(), db_reporter.CertDBCertificateReport(cert_db, log_key))) try: self.__state = self.__state_keeper.read(client_pb2.MonitorState) except state.FileNotFoundError: # TODO(ekasper): initialize state file with a setup script, so we # can raise with certainty when it's not found. logging.warning("Monitor state file not found, assuming first " "run.") else: if not self.__state.HasField("verified_sth"): logging.warning( "No verified monitor state, assuming first run.") # load compact merkle tree state from the monitor state self._verified_tree = merkle.CompactMerkleTree(hasher) self._unverified_tree = merkle.CompactMerkleTree(hasher) self._verified_tree.load(self.__state.verified_tree) self._unverified_tree.load(self.__state.unverified_tree)
def check_state(result): # Check that we updated the state. expected_state = client_pb2.MonitorState() expected_state.verified_sth.CopyFrom(self._DEFAULT_STH) expected_state.pending_sth.CopyFrom(self._NEW_STH) merkle.CompactMerkleTree().save(expected_state.verified_tree) merkle.CompactMerkleTree().save(expected_state.unverified_tree) self.verify_state(expected_state) audited_sths = list(self.db.scan_latest_sth_range("log_server")) self.assertEqual(audited_sths[0].audit.status, client_pb2.VERIFIED) self.assertEqual(audited_sths[1].audit.status, client_pb2.UNVERIFIED) self.assertEqual(len(audited_sths), 2)
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_push_subtree_1(self): for i in xrange(len(TreeHasherTest.test_vector_leaves)): test_vector = TreeHasherTest.test_vector_leaves[:i+1] self.tree = merkle.CompactMerkleTree() self.tree.extend(test_vector) self.tree._push_subtree(["test leaf"]) self.assertEqual(len(self.tree), len(test_vector) + 1)
def test_extend_from_empty(self): for i in xrange(len(TreeHasherTest.test_vector_leaves)): test_vector = TreeHasherTest.test_vector_leaves[:i+1] expected_hash = TreeHasherTest.test_vector_hashes[i] self.tree = merkle.CompactMerkleTree() self.tree.extend(test_vector) self.assertEqual(self.tree.root_hash().encode("hex"), expected_hash)
def dummy_compute_projected_sth(old_sth): sth = client_pb2.SthResponse() sth.timestamp = old_sth.timestamp sth.tree_size = size = old_sth.tree_size tree = merkle.CompactMerkleTree(merkle.TreeHasher(), size, ["a"] * merkle.count_bits_set(size)) f = mock.Mock(return_value=(sth, tree)) f.dummy_sth = sth f.dummy_tree = tree old_sth.sha256_root_hash = tree.root_hash() return f
def test_update_sth(self): client = FakeLogClient(self._NEW_STH) m = self.create_monitor(client) self.assertTrue(m._update_sth()) # Check that we updated the state. expected_state = client_pb2.MonitorState() expected_state.verified_sth.CopyFrom(self._DEFAULT_STH) expected_state.pending_sth.CopyFrom(self._NEW_STH) merkle.CompactMerkleTree().save(expected_state.verified_tree) self.verify_state(expected_state)
def test_extend_from_partial(self): z = len(TreeHasherTest.test_vector_leaves) for i in xrange(z): self.tree = merkle.CompactMerkleTree() # add up to i test_vector = TreeHasherTest.test_vector_leaves[:i+1] expected_hash = TreeHasherTest.test_vector_hashes[i] self.tree.extend(test_vector) self.assertEqual(self.tree.root_hash().encode("hex"), expected_hash) # add up to z test_vector = TreeHasherTest.test_vector_leaves[i+1:] expected_hash = TreeHasherTest.test_vector_hashes[z-1] self.tree.extend(test_vector) self.assertEqual(self.tree.root_hash().encode("hex"), expected_hash)
def setUp(self): self.tree = merkle.CompactMerkleTree(HexTreeHasher())