summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/certkeys.py8
-rw-r--r--tools/certtools.py50
-rwxr-xr-xtools/compileconfig.py2
-rwxr-xr-xtools/create-key.sh4
-rwxr-xr-xtools/fetchallcerts.py5
-rwxr-xr-xtools/merge.py16
-rwxr-xr-xtools/submitcert.py5
-rwxr-xr-xtools/testcase1.py12
-rwxr-xr-xtools/verifysct.py5
9 files changed, 69 insertions, 38 deletions
diff --git a/tools/certkeys.py b/tools/certkeys.py
index 52d61be..43646ef 100644
--- a/tools/certkeys.py
+++ b/tools/certkeys.py
@@ -4,14 +4,6 @@ publickeys = {
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfahLEimAoz2t01p3uMziiLOl/fHTD"
"M0YDOhBRuiBARsV4UvxG2LdNgoIGLrtCzWE0J5APC2em4JlvR8EEEFMoA==",
- "https://127.0.0.1:8080/":
- "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9"
- "PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==",
-
- "https://localhost:8080/":
- "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9"
- "PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==",
-
"https://flimsy.ct.nordu.net/":
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9"
"PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==",
diff --git a/tools/certtools.py b/tools/certtools.py
index 2c97dfb..da5021a 100644
--- a/tools/certtools.py
+++ b/tools/certtools.py
@@ -88,8 +88,15 @@ def get_root_cert(issuer):
return root_cert
+def urlopen(url, data=None):
+ try:
+ opener = urllib2.build_opener(urllib2.HTTPSHandler(context=None))
+ except TypeError:
+ opener = urllib2.build_opener(urllib2.HTTPSHandler())
+ return opener.open(url, data)
+
def get_sth(baseurl):
- result = urllib2.urlopen(baseurl + "ct/v1/get-sth").read()
+ result = urlopen(baseurl + "ct/v1/get-sth").read()
return json.loads(result)
def get_proof_by_hash(baseurl, hash, tree_size):
@@ -97,7 +104,7 @@ def get_proof_by_hash(baseurl, hash, tree_size):
params = urllib.urlencode({"hash":base64.b64encode(hash),
"tree_size":tree_size})
result = \
- urllib2.urlopen(baseurl + "ct/v1/get-proof-by-hash?" + params).read()
+ urlopen(baseurl + "ct/v1/get-proof-by-hash?" + params).read()
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR:", e.read()
@@ -108,7 +115,7 @@ def get_consistency_proof(baseurl, tree_size1, tree_size2):
params = urllib.urlencode({"first":tree_size1,
"second":tree_size2})
result = \
- urllib2.urlopen(baseurl + "ct/v1/get-sth-consistency?" + params).read()
+ urlopen(baseurl + "ct/v1/get-sth-consistency?" + params).read()
return json.loads(result)["consistency"]
except urllib2.HTTPError, e:
print "ERROR:", e.read()
@@ -131,7 +138,7 @@ def unpack_tls_array(packed_data, length_len):
def add_chain(baseurl, submission):
try:
- result = urllib2.urlopen(baseurl + "ct/v1/add-chain", json.dumps(submission)).read()
+ result = urlopen(baseurl + "ct/v1/add-chain", json.dumps(submission)).read()
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR", e.code,":", e.read()
@@ -148,7 +155,7 @@ def add_chain(baseurl, submission):
def add_prechain(baseurl, submission):
try:
- result = urllib2.urlopen(baseurl + "ct/v1/add-pre-chain",
+ result = urlopen(baseurl + "ct/v1/add-pre-chain",
json.dumps(submission)).read()
return json.loads(result)
except urllib2.HTTPError, e:
@@ -167,7 +174,7 @@ def add_prechain(baseurl, submission):
def get_entries(baseurl, start, end):
try:
params = urllib.urlencode({"start":start, "end":end})
- result = urllib2.urlopen(baseurl + "ct/v1/get-entries?" + params).read()
+ result = urlopen(baseurl + "ct/v1/get-entries?" + params).read()
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR:", e.read()
@@ -198,8 +205,9 @@ def encode_signature(hash_alg, signature_alg, unpacked_signature):
signature += tls_array(unpacked_signature, 2)
return signature
-def check_signature(baseurl, signature, data):
- publickey = base64.decodestring(publickeys[baseurl])
+def check_signature(baseurl, signature, data, publickey=None):
+ if publickey == None:
+ publickey = base64.decodestring(publickeys[baseurl])
(hash_alg, signature_alg, unpacked_signature) = decode_signature(signature)
assert hash_alg == 4, \
"hash_alg is %d, expected 4" % (hash_alg,) # sha256
@@ -230,20 +238,25 @@ def check_auth_header(authheader, expected_key, publickeydir, data, path):
return True
def http_request(url, data=None, key=None, verifynode=None, publickeydir="."):
- req = urllib2.Request(url, data)
+ try:
+ opener = urllib2.build_opener(urllib2.HTTPSHandler(context=None))
+ except TypeError:
+ opener = urllib2.build_opener(urllib2.HTTPSHandler())
+
(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
+ data_to_sign = parsed_url.query
method = "GET"
else:
+ data_to_sign = data
method = "POST"
- signature = sk.sign("%s\0%s\0%s" % (method, parsed_url.path, data), hashfunc=hashlib.sha256,
+ signature = sk.sign("%s\0%s\0%s" % (method, parsed_url.path, data_to_sign), hashfunc=hashlib.sha256,
sigencode=ecdsa.util.sigencode_der)
- req.add_header('X-Catlfish-Auth', base64.b64encode(signature) + ";key=" + keyname)
- result = urllib2.urlopen(req)
+ opener.addheaders = [('X-Catlfish-Auth', base64.b64encode(signature) + ";key=" + keyname)]
+ result = opener.open(url, data)
authheader = result.info().get('X-Catlfish-Auth')
data = result.read()
check_auth_header(authheader, verifynode, publickeydir, data, parsed_url.path)
@@ -263,7 +276,7 @@ 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):
+def check_sth_signature(baseurl, sth, publickey=None):
signature = base64.decodestring(sth["tree_head_signature"])
version = struct.pack(">b", 0)
@@ -273,7 +286,7 @@ def check_sth_signature(baseurl, sth):
hash = base64.decodestring(sth["sha256_root_hash"])
tree_head = version + signature_type + timestamp + tree_size + hash
- check_signature(baseurl, signature, tree_head)
+ check_signature(baseurl, signature, tree_head, publickey=publickey)
def create_sth_signature(tree_size, timestamp, root_hash, baseurl, key=None):
version = struct.pack(">b", 0)
@@ -284,8 +297,9 @@ def create_sth_signature(tree_size, timestamp, root_hash, baseurl, key=None):
return create_signature(baseurl, tree_head, key=key)
-def check_sct_signature(baseurl, signed_entry, sct, precert=False):
- publickey = base64.decodestring(publickeys[baseurl])
+def check_sct_signature(baseurl, signed_entry, sct, precert=False, publickey=None):
+ if publickey == None:
+ publickey = base64.decodestring(publickeys[baseurl])
calculated_logid = hashlib.sha256(publickey).digest()
received_logid = base64.decodestring(sct["id"])
assert calculated_logid == received_logid, \
@@ -306,7 +320,7 @@ def check_sct_signature(baseurl, signed_entry, sct, precert=False):
entry_type + signed_entry + \
tls_array(base64.decodestring(sct["extensions"]), 2)
- check_signature(baseurl, signature, signed_struct)
+ check_signature(baseurl, signature, signed_struct, publickey=publickey)
def pack_mtl(timestamp, leafcert):
entry_type = struct.pack(">H", 0)
diff --git a/tools/compileconfig.py b/tools/compileconfig.py
index 4996994..c239bd0 100755
--- a/tools/compileconfig.py
+++ b/tools/compileconfig.py
@@ -158,7 +158,7 @@ def gen_config(nodename, config, localconfig):
bind_publichttpaddress = localconfig.get("publichttpaddresses", {}).get(nodename)
options = localconfig.get("options", [])
- configfile = open(paths["configdir"] + nodename + ".config", "w")
+ configfile = open(paths["configdir"] + "/" + nodename + ".config", "w")
print >>configfile, "%% catlfish configuration file (-*- erlang -*-)"
(nodetype, nodeconfig) = get_node_config(nodename, config)
diff --git a/tools/create-key.sh b/tools/create-key.sh
new file mode 100755
index 0000000..9d29c86
--- /dev/null
+++ b/tools/create-key.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+openssl ecparam -name prime256v1 -genkey -noout -out $1-private.pem
+openssl ec -in $1-private.pem -pubout -out $1.pem
diff --git a/tools/fetchallcerts.py b/tools/fetchallcerts.py
index e0ea92f..395fe69 100755
--- a/tools/fetchallcerts.py
+++ b/tools/fetchallcerts.py
@@ -22,6 +22,7 @@ parser = argparse.ArgumentParser(description='')
parser.add_argument('baseurl', help="Base URL for CT server")
parser.add_argument('--store', default=None, metavar="dir", help='Store certificates in directory dir')
parser.add_argument('--write-sth', action='store_true', help='Write STH')
+parser.add_argument('--publickey', default=None, metavar="file", help='Public key for the CT log')
args = parser.parse_args()
def get_entries_wrapper(baseurl, start, end):
@@ -39,8 +40,10 @@ def print_layer(layer):
for entry in layer:
print base64.b16encode(entry)
+logpublickey = get_public_key_from_file(args.publickey) if args.publickey else None
+
sth = get_sth(args.baseurl)
-check_sth_signature(args.baseurl, sth)
+check_sth_signature(args.baseurl, sth, publickey=logpublickey)
tree_size = sth["tree_size"]
root_hash = base64.decodestring(sth["sha256_root_hash"])
diff --git a/tools/merge.py b/tools/merge.py
index e6fae24..f9c93d9 100755
--- a/tools/merge.py
+++ b/tools/merge.py
@@ -16,7 +16,9 @@ import hashlib
import urlparse
import os
import yaml
-from certtools import build_merkle_tree, create_sth_signature, check_sth_signature, get_eckey_from_file, timing_point, http_request
+from certtools import build_merkle_tree, create_sth_signature, \
+ check_sth_signature, get_eckey_from_file, timing_point, http_request, \
+ get_public_key_from_file
parser = argparse.ArgumentParser(description="")
parser.add_argument('--config', help="System configuration", required=True)
@@ -41,6 +43,8 @@ logorderfile = mergedb + "/logorder"
own_key = (localconfig["nodename"], "%s/%s-private.pem" % (paths["privatekeys"], localconfig["nodename"]))
+logpublickey = get_public_key_from_file(paths["logpublickey"])
+
hashed_dir = True
def parselogrow(row):
@@ -238,19 +242,23 @@ tree_size = len(logorder)
root_hash = tree[-1][0]
timestamp = int(time.time() * 1000)
+tree_head_signature = None
for signingnode in signingnodes:
try:
tree_head_signature = create_sth_signature(tree_size, timestamp,
root_hash, "https://%s/" % signingnode["address"], key=own_key)
break
- except urllib2.URLError:
- pass
+ except urllib2.URLError, e:
+ print e
+if tree_head_signature == None:
+ print >>sys.stderr, "Could not contact any signing nodes"
+ sys.exit(1)
sth = {"tree_size": tree_size, "timestamp": timestamp,
"sha256_root_hash": base64.b64encode(root_hash),
"tree_head_signature": base64.b64encode(tree_head_signature)}
-check_sth_signature(ctbaseurl, sth)
+check_sth_signature(ctbaseurl, sth, publickey=logpublickey)
timing_point(timing, "build sth")
diff --git a/tools/submitcert.py b/tools/submitcert.py
index 2e8cc33..ba4b337 100755
--- a/tools/submitcert.py
+++ b/tools/submitcert.py
@@ -30,6 +30,7 @@ parser.add_argument('--sct-file', default=None, metavar="file", help='Store SCT:
parser.add_argument('--parallel', type=int, default=16, metavar="n", help="Number of parallel submits")
parser.add_argument('--check-sct', action='store_true', help="Check SCT signature")
parser.add_argument('--pre-warm', action='store_true', help="Wait 3 seconds after first submit")
+parser.add_argument('--publickey', default=None, metavar="file", help='Public key for the CT log')
args = parser.parse_args()
from multiprocessing import Pool
@@ -37,6 +38,8 @@ from multiprocessing import Pool
baseurl = args.baseurl
certfilepath = args.store
+logpublickey = get_public_key_from_file(args.publickey) if args.publickey else None
+
lookup_in_log = False
if certfilepath[-1] == "/":
@@ -84,7 +87,7 @@ def submitcert((certfile, cert)):
try:
if args.check_sct:
- check_sct_signature(baseurl, signed_entry, result, precert=precert)
+ check_sct_signature(baseurl, signed_entry, result, precert=precert, publickey=logpublickey)
timing_point(timing, "checksig")
except AssertionError, e:
print "ERROR:", certfile, e
diff --git a/tools/testcase1.py b/tools/testcase1.py
index 4502b56..1d46230 100755
--- a/tools/testcase1.py
+++ b/tools/testcase1.py
@@ -14,7 +14,9 @@ import hashlib
import itertools
from certtools import *
-baseurls = ["https://127.0.0.1:8080/"]
+baseurls = [sys.argv[1]]
+logpublickeyfile = sys.argv[2]
+
certfiles = ["../tools/testcerts/cert1.txt", "../tools/testcerts/cert2.txt",
"../tools/testcerts/cert3.txt", "../tools/testcerts/cert4.txt",
"../tools/testcerts/cert5.txt"]
@@ -28,6 +30,8 @@ cc5 = get_certs_from_file(certfiles[4])
failures = 0
indentation = ""
+logpublickey = get_public_key_from_file(logpublickeyfile)
+
def testgroup(name):
global indentation
print name + ":"
@@ -55,7 +59,7 @@ def print_and_check_tree_size(expected, baseurl):
global failures
sth = get_sth(baseurl)
try:
- check_sth_signature(baseurl, sth)
+ check_sth_signature(baseurl, sth, publickey=logpublickey)
except AssertionError, e:
print_error("%s", e)
except ecdsa.keys.BadSignatureError, e:
@@ -71,13 +75,13 @@ def do_add_chain(chain, baseurl):
print_error("%s", e)
try:
signed_entry = pack_cert(chain[0])
- check_sct_signature(baseurl, signed_entry, result)
+ check_sct_signature(baseurl, signed_entry, result, publickey=logpublickey)
+ print_success("signature check succeeded")
except AssertionError, e:
print_error("%s", e)
except ecdsa.keys.BadSignatureError, e:
print e
print_error("bad SCT signature")
- print_success("signature check succeeded")
return result
def get_and_validate_proof(timestamp, chain, leaf_index, nentries, baseurl):
diff --git a/tools/verifysct.py b/tools/verifysct.py
index 27ab4c9..4b8e38a 100755
--- a/tools/verifysct.py
+++ b/tools/verifysct.py
@@ -22,12 +22,15 @@ parser = argparse.ArgumentParser(description='')
parser.add_argument('baseurl', help="Base URL for CT server")
parser.add_argument('--sct-file', default=None, metavar="dir", help='SCT:s to verify')
parser.add_argument('--parallel', type=int, default=16, metavar="n", help="Number of parallel verifications")
+parser.add_argument('--publickey', default=None, metavar="file", help='Public key for the CT log')
args = parser.parse_args()
from multiprocessing import Pool
baseurl = args.baseurl
+logpublickey = get_public_key_from_file(args.publickey) if args.publickey else None
+
sth = get_sth(baseurl)
def verifysct(sctentry):
@@ -43,7 +46,7 @@ def verifysct(sctentry):
signed_entry = pack_precert(leafcert, issuer_key_hash)
else:
signed_entry = pack_cert(leafcert)
- check_sct_signature(baseurl, signed_entry, sctentry["sct"], precert=issuer_key_hash)
+ check_sct_signature(baseurl, signed_entry, sctentry["sct"], precert=issuer_key_hash, publickey=logpublickey)
timing_point(timing, "checksig")
except AssertionError, e:
print "ERROR:", e