From 832dba2e1cd4e6e6ff9e8ea7afa98eebb44595e5 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Wed, 28 Jan 2015 13:42:06 +0100 Subject: Move hardcoded merge parameters to command line --- tools/certtools.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index cbb4ff7..af94fb8 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -42,22 +42,31 @@ def get_cert_info(s): result[key] = value return result -def get_certs_from_file(certfile): - certs = [] - cert = "" - incert = False - for line in open(certfile): +def get_pemlike(filename, marker): + entries = [] + entry = "" + inentry = False + + for line in open(filename): line = line.strip() - if line == "-----BEGIN CERTIFICATE-----": - cert = "" - incert = True - elif line == "-----END CERTIFICATE-----": - certs.append(base64.decodestring(cert)) - incert = False - elif incert: - cert += line - return certs + if line == "-----BEGIN " + marker + "-----": + entry = "" + inentry = True + elif line == "-----END " + marker + "-----": + entries.append(base64.decodestring(entry)) + inentry = False + elif inentry: + entry += line + return entries + +def get_certs_from_file(certfile): + return get_pemlike(certfile, "CERTIFICATE") + +def get_eckey_from_file(keyfile): + keys = get_pemlike(keyfile, "EC PRIVATE KEY") + assert len(keys) == 1 + return keys[0] def get_root_cert(issuer): accepted_certs = \ -- cgit v1.1 From b24f6ae5a129b5f0cbbffcf07b5482eda8a3eef2 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Sun, 8 Feb 2015 01:53:40 +0100 Subject: Wait after first submission. Continue on http error 400. Print submission rate and number of submissions every 1000 submissions. --- tools/certtools.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index af94fb8..e1ca57a 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -117,7 +117,9 @@ def add_chain(baseurl, submission): json.dumps(submission)).read() return json.loads(result) except urllib2.HTTPError, e: - print "ERROR:", e.read() + print "ERROR", e.code,":", e.read() + if e.code == 400: + return None sys.exit(1) except ValueError, e: print "==== FAILED REQUEST ====" -- cgit v1.1 From ec31631bb097be9780c7355d4183bfd5050c5af4 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Thu, 19 Feb 2015 13:39:19 +0100 Subject: fetchallcerts.py: handle precerts submitcert.py: handle .zip files fetchallcerts.py: Always calculate full tree fetchallcerts.py: Cache level 16 hashes fetchallcerts.py: Save STH --- tools/certtools.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index e1ca57a..6a144c9 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -11,6 +11,8 @@ import sys import hashlib import ecdsa import datetime +import cStringIO +import zipfile publickeys = { "https://ct.googleapis.com/pilot/": @@ -44,11 +46,14 @@ def get_cert_info(s): def get_pemlike(filename, marker): + return get_pemlike_from_file(open(filename), marker) + +def get_pemlike_from_file(f, marker): entries = [] entry = "" inentry = False - for line in open(filename): + for line in f: line = line.strip() if line == "-----BEGIN " + marker + "-----": entry = "" @@ -63,6 +68,10 @@ def get_pemlike(filename, marker): def get_certs_from_file(certfile): return get_pemlike(certfile, "CERTIFICATE") +def get_certs_from_string(s): + f = cStringIO.StringIO(s) + return get_pemlike_from_file(f, "CERTIFICATE") + def get_eckey_from_file(keyfile): keys = get_pemlike(keyfile, "EC PRIVATE KEY") assert len(keys) == 1 @@ -138,6 +147,10 @@ def get_entries(baseurl, start, end): print "ERROR:", e.read() sys.exit(1) +def extract_precertificate(precert_chain_entry): + (precert, certchain) = unpack_tls_array(precert_chain_entry, 3) + return (precert, certchain) + def decode_certificate_chain(packed_certchain): (unpacked_certchain, rest) = unpack_tls_array(packed_certchain, 3) assert len(rest) == 0 @@ -235,8 +248,13 @@ def unpack_mtl(merkle_tree_leaf): leaf_type = merkle_tree_leaf[1:2] timestamped_entry = merkle_tree_leaf[2:] (timestamp, entry_type) = struct.unpack(">QH", timestamped_entry[0:10]) - (leafcert, rest_entry) = unpack_tls_array(timestamped_entry[10:], 3) - return (leafcert, timestamp) + if entry_type == 0: + issuer_key_hash = None + (leafcert, rest_entry) = unpack_tls_array(timestamped_entry[10:], 3) + elif entry_type == 1: + issuer_key_hash = timestamped_entry[10:42] + (leafcert, rest_entry) = unpack_tls_array(timestamped_entry[42:], 3) + return (leafcert, timestamp, issuer_key_hash) def get_leaf_hash(merkle_tree_leaf): leaf_hash = hashlib.sha256() @@ -284,3 +302,72 @@ def build_merkle_tree(layer0): current_layer = next_merkle_layer(current_layer) layers.append(current_layer) return layers + +def print_inclusion_proof(proof): + audit_path = proof[u'audit_path'] + n = proof[u'leaf_index'] + level = 0 + for s in audit_path: + entry = base64.b16encode(base64.b64decode(s)) + n ^= 1 + print level, n, entry + n >>= 1 + level += 1 + +def get_one_cert(store, i): + filename = i / 10000 + zf = zipfile.ZipFile("%s/%04d.zip" % (store, i / 10000)) + cert = zf.read("%08d" % i) + zf.close() + return cert + +def get_hash_from_certfile(cert): + for line in cert.split("\n"): + if line.startswith("-----"): + return None + if line.startswith("Leafhash: "): + return base64.b16decode(line[len("Leafhash: "):]) + return None + +def get_proof(store, tree_size, n): + hash = get_hash_from_certfile(get_one_cert(store, n)) + return get_proof_by_hash(args.baseurl, hash, tree_size) + +def get_certs_from_zipfiles(zipfiles, firstleaf, lastleaf): + for i in range(firstleaf, lastleaf + 1): + try: + yield zipfiles[i / 10000].read("%08d" % i) + except KeyError: + return + +def get_merkle_hash_64k(store, blocknumber, write_to_cache=False): + hashfilename = "%s/%04x.64khash" % (store, blocknumber) + try: + hash = base64.b16decode(open(hashfilename).read()) + assert len(hash) == 32 + return ("hash", hash) + except IOError: + pass + firstleaf = blocknumber * 65536 + lastleaf = firstleaf + 65535 + firstfile = firstleaf / 10000 + lastfile = lastleaf / 10000 + zipfiles = {} + for i in range(firstfile, lastfile + 1): + try: + zipfiles[i] = zipfile.ZipFile("%s/%04d.zip" % (store, i)) + except IOError: + break + certs = get_certs_from_zipfiles(zipfiles, firstleaf, lastleaf) + layer0 = [get_hash_from_certfile(cert) for cert in certs] + tree = build_merkle_tree(layer0) + calculated_hash = tree[-1][0] + for zf in zipfiles.values(): + zf.close() + if len(layer0) != 65536: + return ("incomplete", (len(layer0), calculated_hash)) + if write_to_cache: + f = open(hashfilename, "w") + f.write(base64.b16encode(calculated_hash)) + f.close() + return ("hash", calculated_hash) -- cgit v1.1 From 31589e4fe5485cd05c4f28b759d90d4ab754123e Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Sun, 15 Feb 2015 15:23:29 +0100 Subject: Implement function to fetch consistency proof Implement function to calculate tree head from disk Implement function to calculate an intermediate node from disk --- tools/certtools.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 9 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index 6a144c9..31045b9 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -105,6 +105,17 @@ def get_proof_by_hash(baseurl, hash, tree_size): print "ERROR:", e.read() sys.exit(1) +def get_consistency_proof(baseurl, tree_size1, tree_size2): + try: + params = urllib.urlencode({"first":tree_size1, + "second":tree_size2}) + result = \ + urllib2.urlopen(baseurl + "ct/v1/get-sth-consistency?" + params).read() + return json.loads(result)["consistency"] + except urllib2.HTTPError, e: + print "ERROR:", e.read() + sys.exit(1) + def tls_array(data, length_len): length_bytes = struct.pack(">Q", len(data))[-length_len:] return length_bytes + data @@ -340,16 +351,24 @@ def get_certs_from_zipfiles(zipfiles, firstleaf, lastleaf): except KeyError: return -def get_merkle_hash_64k(store, blocknumber, write_to_cache=False): - hashfilename = "%s/%04x.64khash" % (store, blocknumber) - try: - hash = base64.b16decode(open(hashfilename).read()) - assert len(hash) == 32 - return ("hash", hash) - except IOError: - pass +def get_merkle_hash_64k(store, blocknumber, write_to_cache=False, treesize=None): firstleaf = blocknumber * 65536 lastleaf = firstleaf + 65535 + if treesize != None: + assert firstleaf < treesize + usecache = lastleaf < treesize + lastleaf = min(lastleaf, treesize - 1) + else: + usecache = True + + hashfilename = "%s/%04x.64khash" % (store, blocknumber) + if usecache: + try: + hash = base64.b16decode(open(hashfilename).read()) + assert len(hash) == 32 + return ("hash", hash) + except IOError: + pass firstfile = firstleaf / 10000 lastfile = lastleaf / 10000 zipfiles = {} @@ -364,10 +383,81 @@ def get_merkle_hash_64k(store, blocknumber, write_to_cache=False): calculated_hash = tree[-1][0] for zf in zipfiles.values(): zf.close() - if len(layer0) != 65536: + if len(layer0) != lastleaf - firstleaf + 1: return ("incomplete", (len(layer0), calculated_hash)) if write_to_cache: f = open(hashfilename, "w") f.write(base64.b16encode(calculated_hash)) f.close() return ("hash", calculated_hash) + +def get_tree_head(store, treesize): + merkle_64klayer = [] + + for blocknumber in range(0, (treesize / 65536) + 1): + (resulttype, result) = get_merkle_hash_64k(store, blocknumber, treesize=treesize) + if resulttype == "incomplete": + print >>sys.stderr, "Couldn't read until tree size", treesize + (incompletelength, hash) = result + print >>sys.stderr, "Stopped at", blocknumber * 65536 + incompletelength + sys.exit(1) + assert resulttype == "hash" + hash = result + merkle_64klayer.append(hash) + #print >>sys.stderr, print blocknumber * 65536, + sys.stdout.flush() + tree = build_merkle_tree(merkle_64klayer) + calculated_root_hash = tree[-1][0] + return calculated_root_hash + +def get_intermediate_hash(store, treesize, level, index): + if level >= 16: + merkle_64klayer = [] + + levelsize = (2**(level-16)) + + for blocknumber in range(index * levelsize, (index + 1) * levelsize): + if blocknumber * (2 ** 16) >= treesize: + break + #print "looking at block", blocknumber + (resulttype, result) = get_merkle_hash_64k(store, blocknumber, treesize=treesize) + if resulttype == "incomplete": + print >>sys.stderr, "Couldn't read until tree size", treesize + (incompletelength, hash) = result + print >>sys.stderr, "Stopped at", blocknumber * 65536 + incompletelength + sys.exit(1) + assert resulttype == "hash" + hash = result + #print "block hash", base64.b16encode(hash) + merkle_64klayer.append(hash) + #print >>sys.stderr, print blocknumber * 65536, + sys.stdout.flush() + tree = build_merkle_tree(merkle_64klayer) + return tree[-1][0] + else: + levelsize = 2 ** level + firstleaf = index * levelsize + lastleaf = firstleaf + levelsize - 1 + #print "firstleaf", firstleaf + #print "lastleaf", lastleaf + assert firstleaf < treesize + lastleaf = min(lastleaf, treesize - 1) + #print "modified lastleaf", lastleaf + firstfile = firstleaf / 10000 + lastfile = lastleaf / 10000 + #print "files", firstfile, lastfile + zipfiles = {} + for i in range(firstfile, lastfile + 1): + try: + zipfiles[i] = zipfile.ZipFile("%s/%04d.zip" % (store, i)) + except IOError: + break + certs = get_certs_from_zipfiles(zipfiles, firstleaf, lastleaf) + layer0 = [get_hash_from_certfile(cert) for cert in certs] + #print "layer0", repr(layer0) + tree = build_merkle_tree(layer0) + calculated_hash = tree[-1][0] + for zf in zipfiles.values(): + zf.close() + assert len(layer0) == lastleaf - firstleaf + 1 + return calculated_hash -- cgit v1.1 From 74a4460cba73877830b73742be76cd2bf0d5f47b Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Thu, 19 Feb 2015 16:23:25 +0100 Subject: Added verification of consistency proofs --- tools/certtools.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index 31045b9..5b556cf 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -461,3 +461,92 @@ def get_intermediate_hash(store, treesize, level, index): zf.close() assert len(layer0) == lastleaf - firstleaf + 1 return calculated_hash + +def bits(n): + p = 0 + while n > 0: + n >>= 1 + p += 1 + return p + +def merkle_height(n): + if n == 0: + return 1 + return bits(n - 1) + +def node_above((pathp, pathl), levels=1): + return (pathp >> levels, pathl + levels) + +def node_even((pathp, pathl)): + return pathp & 1 == 0 + +def node_odd((pathp, pathl)): + return pathp & 1 == 1 + +def node_lower((path1p, path1l), (path2p, path2l)): + return path1l < path2l + +def node_higher((path1p, path1l), (path2p, path2l)): + return path1l > path2l + +def node_level((path1p, path1l)): + return path1l + +def node_outside((path1p, path1l), (path2p, path2l)): + assert path1l == path2l + return path1p > path2p + +def combine_two_hashes((path1, hash1), (path2, hash2), treesize): + assert not node_higher(path1, path2) + edge_node = (treesize - 1, 0) + + if node_lower(path1, path2): + assert path1 == node_above(edge_node, levels=node_level(path1)) + while node_even(path1): + path1 = node_above(path1) + + assert node_above(path1) == node_above(path2) + assert (node_even(path1) and node_odd(path2)) or (node_odd(path1) and node_even(path2)) + + if node_outside(path2, node_above(edge_node, levels=node_level(path2))): + return (node_above(path1), hash1) + + if node_even(path1): + newhash = internal_hash((hash1, hash2)) + else: + newhash = internal_hash((hash2, hash1)) + + return (node_above(path1), newhash) + +def path_as_string(pos, level, treesize): + height = merkle_height(treesize) + path = "{0:0{width}b}".format(pos, width=height - level) + if height == level: + return "" + return path + +def nodes_for_pos(pos, treesize): + height = merkle_height(treesize) + nodes = [] + level = 0 + while pos > 0 and pos & 1 == 0: + pos >>= 1 + level += 1 + if pos & 1: + nodes.append((pos ^ 1, level)) + #print pos, level + while level < height: + pos_level0 = pos * (2 ** level) + #print pos, level + if pos_level0 < treesize: + nodes.append((pos, level)) + pos >>= 1 + pos ^= 1 + level += 1 + return nodes + +def verify_consistency_proof(consistency_proof, first, second): + chain = zip(nodes_for_pos(first, second), consistency_proof) + (_, hash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, second), chain) + (_, oldhash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, first), chain) + return (oldhash, hash) -- cgit v1.1 From 8fa65d708aa1bb44609c2fdc755520e21328b175 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Thu, 19 Feb 2015 19:14:13 +0100 Subject: Move public keys to separate file --- tools/certtools.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index 5b556cf..11e09bb 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -13,20 +13,7 @@ import ecdsa import datetime import cStringIO import zipfile - -publickeys = { - "https://ct.googleapis.com/pilot/": - "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfahLEimAoz2t01p3uMziiLOl/fHTD" - "M0YDOhBRuiBARsV4UvxG2LdNgoIGLrtCzWE0J5APC2em4JlvR8EEEFMoA==", - - "https://127.0.0.1:8080/": - "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9" - "PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==", - - "https://flimsy.ct.nordu.net/": - "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9" - "PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==", -} +from certkeys import publickeys def get_cert_info(s): p = subprocess.Popen( -- cgit v1.1 From 81a35a696d813ac5803afe602e549b56a9dfd9c4 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Fri, 20 Feb 2015 01:58:17 +0100 Subject: testcase1: Actually verify inclusion proof --- tools/certtools.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index 11e09bb..fdff0e1 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -512,10 +512,11 @@ def path_as_string(pos, level, treesize): return "" return path -def nodes_for_pos(pos, treesize): +def nodes_for_subtree(subtreesize, treesize): height = merkle_height(treesize) nodes = [] level = 0 + pos = subtreesize while pos > 0 and pos & 1 == 0: pos >>= 1 level += 1 @@ -532,8 +533,29 @@ def nodes_for_pos(pos, treesize): level += 1 return nodes +def nodes_for_index(pos, treesize): + height = merkle_height(treesize) + nodes = [] + level = 0 + pos ^= 1 + #print pos, level + while level < height: + pos_level0 = pos * (2 ** level) + #print pos, level + if pos_level0 < treesize: + nodes.append((pos, level)) + pos >>= 1 + pos ^= 1 + level += 1 + return nodes + def verify_consistency_proof(consistency_proof, first, second): - chain = zip(nodes_for_pos(first, second), consistency_proof) + chain = zip(nodes_for_subtree(first, second), consistency_proof) (_, hash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, second), chain) (_, oldhash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, first), chain) return (oldhash, hash) + +def verify_inclusion_proof(inclusion_proof, index, treesize, leafhash): + chain = zip([(index, 0)] + nodes_for_index(index, treesize), [leafhash] + inclusion_proof) + (_, hash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, treesize), chain) + return hash -- cgit v1.1 From bdfa89bcf0b8f65554baabda52b107a2ab36690a Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Mon, 23 Feb 2015 12:01:20 +0100 Subject: Add consistency proof checking to testcase1 Fix consistency proof checking when first size is power of 2 --- tools/certtools.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index fdff0e1..2fb1492 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -549,8 +549,11 @@ def nodes_for_index(pos, treesize): level += 1 return nodes -def verify_consistency_proof(consistency_proof, first, second): +def verify_consistency_proof(consistency_proof, first, second, oldhash_input): + if 2 ** bits(first - 1) == first: + consistency_proof = [oldhash_input] + consistency_proof chain = zip(nodes_for_subtree(first, second), consistency_proof) + assert len(nodes_for_subtree(first, second)) == len(consistency_proof) (_, hash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, second), chain) (_, oldhash) = reduce(lambda e1, e2: combine_two_hashes(e1, e2, first), chain) return (oldhash, hash) -- cgit v1.1 From 4e1bcab3f91f975a19710a4350bbee0e9af5168e Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Tue, 3 Mar 2015 14:03:05 +0100 Subject: Move http_request to certtools --- tools/certtools.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index 2fb1492..ad90e5c 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -6,6 +6,7 @@ import json import base64 import urllib import urllib2 +import urlparse import struct import sys import hashlib @@ -182,6 +183,23 @@ def check_signature(baseurl, signature, data): vk.verify(unpacked_signature, data, hashfunc=hashlib.sha256, sigdecode=ecdsa.util.sigdecode_der) +def http_request(url, data=None, key=None): + req = urllib2.Request(url, data) + (keyname, keyfile) = key + privatekey = get_eckey_from_file(keyfile) + sk = ecdsa.SigningKey.from_der(privatekey) + parsed_url = urlparse.urlparse(url) + if data == None: + data = parsed_url.query + method = "GET" + else: + method = "POST" + signature = sk.sign("%s\0%s\0%s" % (method, parsed_url.path, data), hashfunc=hashlib.sha256, + sigencode=ecdsa.util.sigencode_der) + req.add_header('X-Catlfish-Auth', base64.b64encode(signature) + ";key=" + keyname) + result = urllib2.urlopen(req).read() + return result + def create_signature(privatekey, data): sk = ecdsa.SigningKey.from_der(privatekey) unpacked_signature = sk.sign(data, hashfunc=hashlib.sha256, -- cgit v1.1 From ff18e0fdd57a6b485f427173fe7febee03345037 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Tue, 3 Mar 2015 15:33:39 +0100 Subject: merge.py: use external signing --- tools/certtools.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'tools/certtools.py') diff --git a/tools/certtools.py b/tools/certtools.py index ad90e5c..222497f 100644 --- a/tools/certtools.py +++ b/tools/certtools.py @@ -200,10 +200,18 @@ def http_request(url, data=None, key=None): result = urllib2.urlopen(req).read() return result -def create_signature(privatekey, data): - sk = ecdsa.SigningKey.from_der(privatekey) - unpacked_signature = sk.sign(data, hashfunc=hashlib.sha256, - sigencode=ecdsa.util.sigencode_der) +def get_signature(baseurl, data, key=None): + try: + params = json.dumps({"plop_version":1, "data": base64.b64encode(data)}) + result = http_request(baseurl + "ct/signing/sth", params, key=key) + parsed_result = json.loads(result) + return base64.b64decode(parsed_result.get(u"result")) + except urllib2.HTTPError, e: + print "ERROR: get_signature", e.read() + sys.exit(1) + +def create_signature(baseurl, data, key=None): + unpacked_signature = get_signature(baseurl, data, key) return encode_signature(4, 3, unpacked_signature) def check_sth_signature(baseurl, sth): @@ -218,14 +226,14 @@ def check_sth_signature(baseurl, sth): check_signature(baseurl, signature, tree_head) -def create_sth_signature(tree_size, timestamp, root_hash, privatekey): +def create_sth_signature(tree_size, timestamp, root_hash, baseurl, key=None): version = struct.pack(">b", 0) signature_type = struct.pack(">b", 1) timestamp_packed = struct.pack(">Q", timestamp) tree_size_packed = struct.pack(">Q", tree_size) tree_head = version + signature_type + timestamp_packed + tree_size_packed + root_hash - return create_signature(privatekey, tree_head) + return create_signature(baseurl, tree_head, key=key) def check_sct_signature(baseurl, leafcert, sct): publickey = base64.decodestring(publickeys[baseurl]) -- cgit v1.1