3 from allmydata.util import keyutil, base32
5 def make_index(ann, key_s):
6 """Return something that can be used as an index (e.g. a tuple of
7 strings), such that two messages that refer to the same 'thing' will have
8 the same index. This is a tuple of (service-name, signing-key, None) for
9 signed announcements, or (service-name, None, tubid) for unsigned
12 service_name = str(ann["service-name"])
14 return (service_name, key_s, None)
16 tubid = get_tubid_string_from_ann(ann)
17 return (service_name, None, tubid)
19 def get_tubid_string_from_ann(ann):
20 return get_tubid_string(str(ann.get("anonymous-storage-FURL")
23 def get_tubid_string(furl):
24 m = re.match(r'pb://(\w+)@', furl)
26 return m.group(1).lower()
28 def convert_announcement_v1_to_v2(ann_t):
29 (furl, service_name, ri_name, nickname, ver, oldest) = ann_t
30 assert type(furl) is str
31 assert type(service_name) is str
33 assert type(nickname) is str
34 assert type(ver) is str
35 assert type(oldest) is str
37 "nickname": nickname.decode("utf-8"),
40 "oldest-supported": oldest,
42 "service-name": service_name,
43 "anonymous-storage-FURL": furl,
44 "permutation-seed-base32": get_tubid_string(furl),
46 msg = simplejson.dumps(ann).encode("utf-8")
47 return (msg, None, None)
49 def convert_announcement_v2_to_v1(ann_v2):
50 (msg, sig, pubkey) = ann_v2
51 ann = simplejson.loads(msg)
52 assert ann["version"] == 0
53 ann_t = (str(ann["anonymous-storage-FURL"]),
54 str(ann["service-name"]),
55 "remoteinterface-name is unused",
56 ann["nickname"].encode("utf-8"),
57 str(ann["my-version"]),
58 str(ann["oldest-supported"]),
63 def sign_to_foolscap(ann, sk):
64 # return (bytes, None, None) or (bytes, sig-str, pubkey-str). A future
65 # HTTP-based serialization will use JSON({msg:b64(JSON(msg).utf8),
66 # sig:v0-b64(sig), pubkey:v0-b64(pubkey)}) .
67 msg = simplejson.dumps(ann).encode("utf-8")
69 sig = "v0-"+base32.b2a(sk.sign(msg))
70 vk_bytes = sk.get_verifying_key_bytes()
71 ann_t = (msg, sig, "v0-"+base32.b2a(vk_bytes))
73 ann_t = (msg, None, None)
76 class UnknownKeyError(Exception):
79 def unsign_from_foolscap(ann_t):
80 (msg, sig_vs, claimed_key_vs) = ann_t
82 if sig_vs and claimed_key_vs:
83 if not sig_vs.startswith("v0-"):
84 raise UnknownKeyError("only v0- signatures recognized")
85 if not claimed_key_vs.startswith("v0-"):
86 raise UnknownKeyError("only v0- keys recognized")
87 claimed_key = keyutil.parse_pubkey("pub-"+claimed_key_vs)
88 sig_bytes = base32.a2b(keyutil.remove_prefix(sig_vs, "v0-"))
89 claimed_key.verify(sig_bytes, msg)
90 key_vs = claimed_key_vs
91 ann = simplejson.loads(msg.decode("utf-8"))