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_hash_full_tree(self): hasher = merkle.TreeHasher() self.assertEqual(hasher.hash_full_tree([]), hasher.hash_empty()) l = iter(hasher.hash_leaf(c) for c in "abcde").next h = hasher.hash_children root_hash = h(h(h(l(), l()), h(l(), l())), l()) self.assertEqual(hasher.hash_full_tree("abcde"), root_hash)
def test_get_proof_by_hash(self): client = self.default_client() entry = test_util.make_entry(1) hasher = merkle.TreeHasher() leaf_hash = hasher.hash_leaf(entry.leaf_input) proof_by_hash = client.get_proof_by_hash(leaf_hash, 2) self.assertEqual(proof_by_hash.audit_path, test_util.DEFAULT_FAKE_PROOF) self.assertEqual(proof_by_hash.leaf_index, 1)
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_tree_snapshot_root_hash(self): """Test root hash calculation. Test that root hash is calculated correctly when all leaves are added at once. """ tree = in_memory_merkle_tree.InMemoryMerkleTree(TEST_VECTOR_DATA) hasher = merkle.TreeHasher() for i in range(len(TEST_VECTOR_DATA)): self.assertEqual( tree.get_root_hash(i), hasher.hash_full_tree(TEST_VECTOR_DATA[0:i]))
def test_tree_incremental_root_hash(self): """Test root hash calculation. Test that root hash is calculated correctly when leaves are added incrementally. """ tree = in_memory_merkle_tree.InMemoryMerkleTree([]) hasher = merkle.TreeHasher() for i in range(len(TEST_VECTOR_DATA)): tree.add_leaf(TEST_VECTOR_DATA[i]) self.assertEqual( tree.get_root_hash(), hasher.hash_full_tree(TEST_VECTOR_DATA[0:i+1]))
def get_proof_by_hash(self, leaf_hash, tree_size): """If the hash is known, return a (fake) audit proof.""" if (not leaf_hash or tree_size <= 0 or tree_size > self._sth.tree_size): return self.make_response(400, "Bad Request") hasher = merkle.TreeHasher() for i in range(self._sth.tree_size): entry = make_entry(i) if hasher.hash_leaf(entry.leaf_input) == leaf_hash: return self.make_response(200, "OK", json_content=proof_and_index_to_json( DEFAULT_FAKE_PROOF, i)) # Not found return self.make_response(400, "Bad Request")
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 setUp(self): if not FLAGS.verbose_tests: logging.disable(logging.CRITICAL) self.db = sqlite_log_db.SQLiteLogDB( sqlitecon.SQLiteConnectionManager(":memory:", keepalive=True)) self.temp_db = sqlite_temp_db.SQLiteTempDB( sqlitecon.SQLiteConnectionManager(":memory:", keepalive=True)) default_state = client_pb2.MonitorState() default_state.verified_sth.CopyFrom(self._DEFAULT_STH) self.state_keeper = InMemoryStateKeeper(default_state) self.verifier = mock.Mock() self.hasher = merkle.TreeHasher() # Make sure the DB knows about the default log server. log = client_pb2.CtLogMetadata() log.log_server = "log_server" self.db.add_log(log)
def setUp(self): if not FLAGS.verbose_tests: logging.disable(logging.CRITICAL) self.db = sqlite_log_db.SQLiteLogDB( sqlitecon.SQLiteConnectionManager(":memory:", keepalive=True)) # We can't simply use DB in memory with keepalive True, because different # thread is writing to the database which results in an sqlite exception. self.cert_db = mock.MagicMock() self.state_keeper = InMemoryStateKeeper( copy.deepcopy(self._DEFAULT_STATE)) self.verifier = mock.Mock() self.hasher = merkle.TreeHasher() # Make sure the DB knows about the default log server. log = client_pb2.CtLogMetadata() log.log_server = "log_server" self.db.add_log(log)
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)
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
def __init__(self, leaves): """Start with the array of |leaves| provided.""" self.__leaves = list(leaves) self.__hasher = merkle.TreeHasher()
def __init__(self, hashfunc=hashlib.sha256): self.hasher = merkle.TreeHasher(hashfunc)
def test_hash_full_tree_test_vector(self): hasher = merkle.TreeHasher() for i in xrange(len(TreeHasherTest.test_vector_leaves)): test_vector = TreeHasherTest.test_vector_leaves[:i+1] expected_hash = TreeHasherTest.test_vector_hashes[i].decode("hex") self.assertEqual(hasher.hash_full_tree(test_vector), expected_hash)
def test_hash_full_empty(self): hasher = merkle.TreeHasher() for i in xrange(0, 5): self.assertEqual(hasher._hash_full("abcd", i, i)[0].encode("hex"), TreeHasherTest.sha256_empty_hash)
def test_hash_full_invalid_index(self): hasher = merkle.TreeHasher() self.assertRaises(IndexError, hasher._hash_full, "abcd", -5, -1) self.assertRaises(IndexError, hasher._hash_full, "abcd", -1, 1) self.assertRaises(IndexError, hasher._hash_full, "abcd", 1, 5) self.assertRaises(IndexError, hasher._hash_full, "abcd", 2, 1)
def test_hash_children(self): hasher = merkle.TreeHasher() for left, right, val in TreeHasherTest.sha256_nodes: self.assertEqual(hasher.hash_children( left.decode("hex"), right.decode("hex")).encode("hex"), val)
def test_hash_leaves(self): hasher = merkle.TreeHasher() for leaf, val in TreeHasherTest.sha256_leaves: self.assertEqual(hasher.hash_leaf(leaf.decode("hex")).encode("hex"), val)
def test_empty_hash(self): hasher = merkle.TreeHasher() self.assertEqual(hasher.hash_empty().encode("hex"), TreeHasherTest.sha256_empty_hash)