summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMagnus Ahltorp <map@kth.se>2015-03-31 14:27:23 +0200
committerMagnus Ahltorp <map@kth.se>2015-03-31 14:27:23 +0200
commit6b62ebbf1de5b9e55b04e9cfafd0620f1374c2d4 (patch)
tree80a4dccbd98c26a80c07146a93318ba1edece01f /tools
parent22cefc84254cae1f57195da819eba69dbacb5a6e (diff)
Cleanup tests and use urllib2.build_openercleanup-tests
Remove unused files Generate test config files directly in release directory Move test database files to "tests" directory Generate log key when preparing tests Report error when STH not found in v1.erl Make merge, fetchallcerts, submitcert, verifysct, and testcase1 take log key as argument
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