diff options
-rwxr-xr-x | siglog-witness.py | 88 |
1 files changed, 50 insertions, 38 deletions
diff --git a/siglog-witness.py b/siglog-witness.py index 6beb96e..3b79c8d 100755 --- a/siglog-witness.py +++ b/siglog-witness.py @@ -120,6 +120,18 @@ class TreeHead: assert('signature' in self._text) assert('key_hash' in self._text) + @property + def timestamp(self): + return int(self._text['timestamp']) + + @property + def tree_size(self): + return int(self._text['tree_size']) + + @property + def root_hash(self): + return unhexlify(self._text['root_hash']) + def text(self): text = 'timestamp={}\n'.format(self._text['timestamp']) text += 'tree_size={}\n'.format(self._text['tree_size']) @@ -129,7 +141,7 @@ class TreeHead: return text.encode('ascii') def serialise(self): - data = struct.pack('!QQ', self.timestamp(), self.tree_size()) + data = struct.pack('!QQ', self.timestamp, self.tree_size) data += unhexlify(self._text['root_hash']) assert(len(data) == 48) return data @@ -149,7 +161,7 @@ class TreeHead: return True def timestamp_valid(self, now): - ts_sec = self.timestamp() + ts_sec = self.timestamp ts_asc = time.ctime(ts_sec) if ts_sec < now - 12 * 3600: return (ERR_OK, @@ -159,49 +171,49 @@ class TreeHead: "WARNING: Tree head timestamp too new: {} ({})".format(ts_sec, ts_asc)) def history_valid(self, prev): - if self.tree_size() < prev.tree_size(): + if self.tree_size < prev.tree_size: return (ERR_TREEHEAD_INVALID, - "ERROR: Log is shrinking: {} < {} ".format(self.tree_size(), - prev.tree_size())) + "ERROR: Log is shrinking: {} < {} ".format(self.tree_size, + prev.tree_size)) - if self.timestamp() < prev.timestamp(): + if self.timestamp < prev.timestamp: return (ERR_TREEHEAD_INVALID, - "ERROR: Log is time traveling: {} < {} ".format(time.ctime(self.timestamp()), - time.ctime(prev.timestamp()))) + "ERROR: Log is time traveling: {} < {} ".format(time.ctime(self.timestamp), + time.ctime(prev.timestamp))) - if self.timestamp() == prev.timestamp() and \ - self.root_hash() == prev.root_hash() and \ - self.tree_size() == prev.tree_size(): + if self.timestamp == prev.timestamp and \ + self.root_hash == prev.root_hash and \ + self.tree_size == prev.tree_size: return (ERR_OK, - "INFO: Fetched head of tree of size {} already seen".format(prev.tree_size())) + "INFO: Fetched head of tree of size {} already seen".format(prev.tree_size)) - if self.root_hash() == prev.root_hash() and \ - self.tree_size() != prev.tree_size(): + if self.root_hash == prev.root_hash and \ + self.tree_size != prev.tree_size: return (ERR_TREEHEAD_INVALID, "ERROR: Tree size has changed but hash has not: " - "{}: {} != {}".format(self.root_hash(), - self.tree_size(), - prev.tree_size())) + "{}: {} != {}".format(self.root_hash, + self.tree_size, + prev.tree_size)) - if self.root_hash() != prev.root_hash() and \ - self.tree_size() == prev.tree_size(): + if self.root_hash != prev.root_hash and \ + self.tree_size == prev.tree_size: return (ERR_TREEHEAD_INVALID, "ERROR: Hash has changed but tree size has not: " - "{}: {} != {}".format(self.tree_size(), - self.root_hash(), - prev.root_hash())) + "{}: {} != {}".format(self.tree_size, + self.root_hash, + prev.root_hash)) # Same hash and size but new timestamp is ok. - proof, err = fetch_consistency_proof(prev.tree_size(), self.tree_size()) + proof, err = fetch_consistency_proof(prev.tree_size, self.tree_size) if err: return err if not consistency_proof_valid(prev, self, proof): - errmsg = "ERROR: failing consistency proof check for {}->{}\n".format(prev.tree_size(), - self.tree_size()) - errmsg += "DEBUG: {}:{}->{}:{}\n {}".format(prev.tree_size(), - prev.root_hash(), - self.tree_size(), - self.root_hash(), + errmsg = "ERROR: failing consistency proof check for {}->{}\n".format(prev.tree_size, + self.tree_size) + errmsg += "DEBUG: {}:{}->{}:{}\n {}".format(prev.tree_size, + prev.root_hash, + self.tree_size, + self.root_hash, proof.path()) return ERR_CONSISTENCYPROOF_INVALID, errmsg @@ -290,17 +302,17 @@ def numbits(n): # in RFC6962-BIS, see # https://datatracker.ietf.org/doc/html/draft-ietf-trans-rfc6962-bis-39#section-2.1.4.2 def consistency_proof_valid(first, second, proof): - assert(first.tree_size() == proof.old_size()) - assert(second.tree_size() == proof.new_size()) + assert(first.tree_size == proof.old_size()) + assert(second.tree_size == proof.new_size()) path = proof.path() if len(path) == 0: return False - if numbits(first.tree_size()) == 1: - path = [first.root_hash()] + path + if numbits(first.tree_size) == 1: + path = [first.root_hash] + path - fn = first.tree_size() - 1 - sn = second.tree_size() - 1 + fn = first.tree_size - 1 + sn = second.tree_size - 1 while fn & 1: fn >>= 1 sn >>= 1 @@ -324,7 +336,7 @@ def consistency_proof_valid(first, second, proof): fn >>= 1 sn >>= 1 - return sn == 0 and fr == first.root_hash() and sr == second.root_hash() + return sn == 0 and fr == first.root_hash and sr == second.root_hash def sign_send_store_tree_head(signing_key, tree_head): hash = sha256(signing_key.verify_key.encode()) @@ -449,9 +461,9 @@ def main(args): "verify that the tree it represents is really a superset of an\n" "earlier version of the tree in this log.\n" "\nWe are effectively signing this tree head blindly.\n".format(g_args.base_url, - new_tree_head.tree_size())) + new_tree_head.tree_size)) if user_confirm("Really sign head for tree of size {} and upload " - "the signature?".format(new_tree_head.tree_size())): + "the signature?".format(new_tree_head.tree_size)): err3 = sign_send_store_tree_head(signing_key, new_tree_head) if err3: return err3 |