summaryrefslogtreecommitdiff
path: root/tools/certtools.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/certtools.py')
-rw-r--r--tools/certtools.py41
1 files changed, 40 insertions, 1 deletions
diff --git a/tools/certtools.py b/tools/certtools.py
index 48e7b41..13dad17 100644
--- a/tools/certtools.py
+++ b/tools/certtools.py
@@ -5,6 +5,8 @@ import urllib
import urllib2
import struct
import sys
+import hashlib
+import ecdsa
def get_cert_info(s):
p = subprocess.Popen(
@@ -77,7 +79,9 @@ def unpack_tls_array(packed_data, length_len):
padded_length[-length_len:] = packed_data[:length_len]
(length,) = struct.unpack(">Q", "".join(padded_length))
unpacked_data = packed_data[length_len:length_len+length]
- assert len(unpacked_data) == length
+ assert len(unpacked_data) == length, \
+ "data is only %d bytes long, but length is %d bytes" % \
+ (len(unpacked_data), length)
rest_data = packed_data[length_len+length:]
return (unpacked_data, rest_data)
@@ -107,3 +111,38 @@ def decode_certificate_chain(packed_certchain):
certs.append(cert)
unpacked_certchain = rest
return certs
+
+def decode_signature(signature):
+ (hash_alg, signature_alg) = struct.unpack(">bb", signature[0:2])
+ (unpacked_signature, rest) = unpack_tls_array(signature[2:], 2)
+ assert rest == ""
+ return (hash_alg, signature_alg, unpacked_signature)
+
+def check_signature(publickey, leafcert, sct):
+ calculated_logid = hashlib.sha256(publickey).digest()
+ received_logid = base64.decodestring(sct["id"])
+ assert calculated_logid == received_logid, \
+ "log id is incorrect:\n should be %s\n got %s" % \
+ (calculated_logid.encode("hex_codec"),
+ received_logid.encode("hex_codec"))
+
+ signature = base64.decodestring(sct["signature"])
+
+ version = struct.pack(">b", sct["sct_version"])
+ signature_type = struct.pack(">b", 0)
+ timestamp = struct.pack(">Q", sct["timestamp"])
+ entry_type = struct.pack(">H", 0)
+ signed_struct = version + signature_type + timestamp + \
+ entry_type + tls_array(leafcert, 3) + \
+ tls_array(base64.decodestring(sct["extensions"]), 2)
+
+ (hash_alg, signature_alg, unpacked_signature) = decode_signature(signature)
+ assert hash_alg == 4 # sha256
+ assert signature_alg == 3 # ecdsa
+
+ hash = hashlib.sha256()
+ hash.update(signed_struct)
+
+ vk = ecdsa.VerifyingKey.from_der(publickey)
+ vk.verify(unpacked_signature, signed_struct, hashfunc=hashlib.sha256,
+ sigdecode=ecdsa.util.sigdecode_der)