summaryrefslogtreecommitdiff
path: root/tools/certtools.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/certtools.py')
-rw-r--r--tools/certtools.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/tools/certtools.py b/tools/certtools.py
index 8d64ee4..cbb4ff7 100644
--- a/tools/certtools.py
+++ b/tools/certtools.py
@@ -10,6 +10,7 @@ import struct
import sys
import hashlib
import ecdsa
+import datetime
publickeys = {
"https://ct.googleapis.com/pilot/":
@@ -142,6 +143,11 @@ def decode_signature(signature):
assert rest == ""
return (hash_alg, signature_alg, unpacked_signature)
+def encode_signature(hash_alg, signature_alg, unpacked_signature):
+ signature = struct.pack(">bb", hash_alg, signature_alg)
+ signature += tls_array(unpacked_signature, 2)
+ return signature
+
def check_signature(baseurl, signature, data):
publickey = base64.decodestring(publickeys[baseurl])
(hash_alg, signature_alg, unpacked_signature) = decode_signature(signature)
@@ -154,6 +160,12 @@ def check_signature(baseurl, signature, data):
vk.verify(unpacked_signature, data, hashfunc=hashlib.sha256,
sigdecode=ecdsa.util.sigdecode_der)
+def create_signature(privatekey, data):
+ sk = ecdsa.SigningKey.from_der(privatekey)
+ unpacked_signature = sk.sign(data, hashfunc=hashlib.sha256,
+ sigencode=ecdsa.util.sigencode_der)
+ return encode_signature(4, 3, unpacked_signature)
+
def check_sth_signature(baseurl, sth):
signature = base64.decodestring(sth["tree_head_signature"])
@@ -166,6 +178,15 @@ def check_sth_signature(baseurl, sth):
check_signature(baseurl, signature, tree_head)
+def create_sth_signature(tree_size, timestamp, root_hash, privatekey):
+ 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)
+
def check_sct_signature(baseurl, leafcert, sct):
publickey = base64.decodestring(publickeys[baseurl])
calculated_logid = hashlib.sha256(publickey).digest()
@@ -198,9 +219,57 @@ def pack_mtl(timestamp, leafcert):
merkle_tree_leaf = version + leaf_type + timestamped_entry
return merkle_tree_leaf
+def unpack_mtl(merkle_tree_leaf):
+ version = merkle_tree_leaf[0:1]
+ 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)
+
def get_leaf_hash(merkle_tree_leaf):
leaf_hash = hashlib.sha256()
leaf_hash.update(struct.pack(">b", 0))
leaf_hash.update(merkle_tree_leaf)
return leaf_hash.digest()
+
+def timing_point(timer_dict=None, name=None):
+ t = datetime.datetime.now()
+ if timer_dict:
+ starttime = timer_dict["lasttime"]
+ stoptime = t
+ deltatime = stoptime - starttime
+ timer_dict["deltatimes"].append((name, deltatime.seconds * 1000000 + deltatime.microseconds))
+ timer_dict["lasttime"] = t
+ return None
+ else:
+ timer_dict = {"deltatimes":[], "lasttime":t}
+ return timer_dict
+
+def internal_hash(pair):
+ if len(pair) == 1:
+ return pair[0]
+ else:
+ hash = hashlib.sha256()
+ hash.update(struct.pack(">b", 1))
+ hash.update(pair[0])
+ hash.update(pair[1])
+ return hash.digest()
+
+def chunks(l, n):
+ return [l[i:i+n] for i in range(0, len(l), n)]
+
+def next_merkle_layer(layer):
+ return [internal_hash(pair) for pair in chunks(layer, 2)]
+
+def build_merkle_tree(layer0):
+ if len(layer0) == 0:
+ return [[hashlib.sha256().digest()]]
+ layers = []
+ current_layer = layer0
+ layers.append(current_layer)
+ while len(current_layer) > 1:
+ current_layer = next_merkle_layer(current_layer)
+ layers.append(current_layer)
+ return layers