diff --git a/src/wormhole/codes.py b/src/wormhole/codes.py index a0e73dc..8f982bb 100644 --- a/src/wormhole/codes.py +++ b/src/wormhole/codes.py @@ -1,4 +1,4 @@ -import os, random +import random WORDLIST = ["able", "baker", "charlie"] # TODO: 1024 diff --git a/src/wormhole/transcribe.py b/src/wormhole/transcribe.py index 561ddcc..79521b4 100644 --- a/src/wormhole/transcribe.py +++ b/src/wormhole/transcribe.py @@ -1,4 +1,5 @@ -import time, requests +import time, requests, json +from binascii import hexlify, unhexlify from spake2 import SPAKE2_A, SPAKE2_B from .const import RELAY from .codes import make_code, extract_channel_id @@ -20,6 +21,7 @@ class Initiator: def __init__(self, appid, data, relay=RELAY): self.appid = appid self.data = data + assert relay.endswith("/") self.relay = relay self.started = time.time() self.wait = 2*SECOND @@ -95,12 +97,64 @@ class Receiver: self.code = code self.channel_id = extract_channel_id(code) self.relay = relay + assert relay.endswith("/") + self.started = time.time() + self.wait = 2*SECOND + self.timeout = 3*MINUTE + self.side = "receiver" self.sp = SPAKE2_B(code.encode("ascii"), idA=self.appid+":Initiator", idB=self.appid+":Receiver") def get_data(self): + # post PAKE message + msg = self.sp.start() + post_url = self.relay + "pake/post/%d" % self.channel_id + post_data = {"side": self.side, + "message": hexlify(msg).decode("ascii")} + r = requests.post(post_url, data=json.dumps(post_data)) + r.raise_for_status() + # poll for PAKE response + pake_url = self.relay + "pake/poll/%d" % self.channel_id + post_data = json.dumps({"side": self.side}) + while True: + r = requests.post(pake_url, data=post_data) + r.raise_for_status() + msgs = r.json()["messages"] + if msgs: + break + if time.time() > (self.started + self.timeout): + raise Timeout + time.sleep(self.wait) + pake_msg = unhexlify(msgs[0].encode("ascii")) + self.key = self.sp.finish(pake_msg) + + # post data message + post_url = self.relay + "data/post/%d" % self.channel_id + post_data = json.dumps({"side": self.side, + "message": hexlify(self.data).decode("ascii")}) + r = requests.post(post_url, data=post_data) + r.raise_for_status() + # poll for data message + data_url = self.relay + "data/poll/%d" % self.channel_id + post_data = json.dumps({"side": self.side}) + while True: + r = requests.post(data_url, data=post_data) + r.raise_for_status() + msgs = r.json()["messages"] + if msgs: + break + if time.time() > (self.started + self.timeout): + raise Timeout + time.sleep(self.wait) + data = unhexlify(msgs[0].encode("ascii")) + # deallocate channel - pass + deallocate_url = self.relay + "deallocate/%s" % self.channel_id + post_data = json.dumps({"side": self.side}) + r = requests.post(deallocate, data=post_data) + r.raise_for_status() + + return data