1import argparse 2import json 3import logging 4import sys 5 6import dns.resolver 7import urllib2 8from signedjson.key import decode_verify_key_bytes, write_signing_keys 9from signedjson.sign import verify_signed_json 10from unpaddedbase64 import decode_base64 11 12 13def get_targets(server_name): 14 if ":" in server_name: 15 target, port = server_name.split(":") 16 yield (target, int(port)) 17 return 18 try: 19 answers = dns.resolver.query("_matrix._tcp." + server_name, "SRV") 20 for srv in answers: 21 yield (srv.target, srv.port) 22 except dns.resolver.NXDOMAIN: 23 yield (server_name, 8448) 24 25 26def get_server_keys(server_name, target, port): 27 url = "https://%s:%i/_matrix/key/v1" % (target, port) 28 keys = json.load(urllib2.urlopen(url)) 29 verify_keys = {} 30 for key_id, key_base64 in keys["verify_keys"].items(): 31 verify_key = decode_verify_key_bytes(key_id, decode_base64(key_base64)) 32 verify_signed_json(keys, server_name, verify_key) 33 verify_keys[key_id] = verify_key 34 return verify_keys 35 36 37def main(): 38 39 parser = argparse.ArgumentParser() 40 parser.add_argument("signature_name") 41 parser.add_argument( 42 "input_json", nargs="?", type=argparse.FileType("r"), default=sys.stdin 43 ) 44 45 args = parser.parse_args() 46 logging.basicConfig() 47 48 server_name = args.signature_name 49 keys = {} 50 for target, port in get_targets(server_name): 51 try: 52 keys = get_server_keys(server_name, target, port) 53 print("Using keys from https://%s:%s/_matrix/key/v1" % (target, port)) 54 write_signing_keys(sys.stdout, keys.values()) 55 break 56 except Exception: 57 logging.exception("Error talking to %s:%s", target, port) 58 59 json_to_check = json.load(args.input_json) 60 print("Checking JSON:") 61 for key_id in json_to_check["signatures"][args.signature_name]: 62 try: 63 key = keys[key_id] 64 verify_signed_json(json_to_check, args.signature_name, key) 65 print("PASS %s" % (key_id,)) 66 except Exception: 67 logging.exception("Check for key %s failed" % (key_id,)) 68 print("FAIL %s" % (key_id,)) 69 70 71if __name__ == "__main__": 72 main() 73