wormhole/invitation code is now unicode
This commit is contained in:
parent
7f6410812c
commit
35768d6738
11
docs/api.md
11
docs/api.md
|
@ -157,8 +157,8 @@ include randomly-selected words or characters. Dice, coin flips, shuffled
|
||||||
cards, or repeated sampling of a high-resolution stopwatch are all useful
|
cards, or repeated sampling of a high-resolution stopwatch are all useful
|
||||||
techniques.
|
techniques.
|
||||||
|
|
||||||
Note that the code is a human-readable string (the python "str" type: so
|
Note that the code is a human-readable string (the python "unicode" type in
|
||||||
unicode in python3, plain bytes in python2).
|
python2, "str" in python3).
|
||||||
|
|
||||||
## Application Identifier
|
## Application Identifier
|
||||||
|
|
||||||
|
@ -248,13 +248,10 @@ python2, "bytes" in python3):
|
||||||
* data in/out
|
* data in/out
|
||||||
* transit records in/out
|
* transit records in/out
|
||||||
|
|
||||||
Some human-readable parameters are passed as strings: "str" in python2, "str"
|
Other (human-facing) values are always unicode ("unicode" in python2, "str"
|
||||||
(i.e. unicode) in python3:
|
in python3):
|
||||||
|
|
||||||
* wormhole code
|
* wormhole code
|
||||||
|
|
||||||
And some are always unicode, in both python2 and python3:
|
|
||||||
|
|
||||||
* relay URL
|
* relay URL
|
||||||
* transit URLs
|
* transit URLs
|
||||||
* transit connection hints (e.g. "host:port")
|
* transit connection hints (e.g. "host:port")
|
||||||
|
|
|
@ -186,7 +186,7 @@ class Wormhole:
|
||||||
if self.code is not None: raise UsageError
|
if self.code is not None: raise UsageError
|
||||||
channelid = self._channel_manager.allocate()
|
channelid = self._channel_manager.allocate()
|
||||||
code = codes.make_code(channelid, code_length)
|
code = codes.make_code(channelid, code_length)
|
||||||
assert isinstance(code, str), type(code)
|
assert isinstance(code, type(u"")), type(code)
|
||||||
self._set_code_and_channelid(code)
|
self._set_code_and_channelid(code)
|
||||||
self._start()
|
self._start()
|
||||||
return code
|
return code
|
||||||
|
@ -198,7 +198,7 @@ class Wormhole:
|
||||||
return code
|
return code
|
||||||
|
|
||||||
def set_code(self, code): # used for human-made pre-generated codes
|
def set_code(self, code): # used for human-made pre-generated codes
|
||||||
if not isinstance(code, str): raise UsageError
|
if not isinstance(code, type(u"")): raise UsageError
|
||||||
if self.code is not None: raise UsageError
|
if self.code is not None: raise UsageError
|
||||||
self._set_code_and_channelid(code)
|
self._set_code_and_channelid(code)
|
||||||
self._start()
|
self._start()
|
||||||
|
@ -215,7 +215,7 @@ class Wormhole:
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
# allocate the rest now too, so it can be serialized
|
# allocate the rest now too, so it can be serialized
|
||||||
self.sp = SPAKE2_Symmetric(self.code.encode("ascii"),
|
self.sp = SPAKE2_Symmetric(to_bytes(self.code),
|
||||||
idSymmetric=to_bytes(self._appid))
|
idSymmetric=to_bytes(self._appid))
|
||||||
self.msg1 = self.sp.start()
|
self.msg1 = self.sp.start()
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ def make_code(channel_id, code_length):
|
||||||
words.append(byte_to_odd_word[os.urandom(1)].lower())
|
words.append(byte_to_odd_word[os.urandom(1)].lower())
|
||||||
else:
|
else:
|
||||||
words.append(byte_to_even_word[os.urandom(1)].lower())
|
words.append(byte_to_even_word[os.urandom(1)].lower())
|
||||||
return str(channel_id) + "-" + "-".join(words)
|
return u"%d-%s" % (channel_id, u"-".join(words))
|
||||||
|
|
||||||
def extract_channel_id(code):
|
def extract_channel_id(code):
|
||||||
channel_id = int(code.split("-")[0])
|
channel_id = int(code.split("-")[0])
|
||||||
|
@ -82,7 +82,7 @@ def input_code_with_completion(prompt, get_channel_ids, code_length):
|
||||||
readline.set_completer(c.wrap_completer)
|
readline.set_completer(c.wrap_completer)
|
||||||
readline.set_completer_delims("")
|
readline.set_completer_delims("")
|
||||||
code = six.moves.input(prompt)
|
code = six.moves.input(prompt)
|
||||||
return code
|
return code.decode("utf-8")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
code = input_code_with_completion("Enter wormhole code: ", lambda: [], 2)
|
code = input_code_with_completion("Enter wormhole code: ", lambda: [], 2)
|
||||||
|
|
|
@ -15,7 +15,7 @@ def receive(args):
|
||||||
w = Wormhole(APPID, args.relay_url)
|
w = Wormhole(APPID, args.relay_url)
|
||||||
if args.zeromode:
|
if args.zeromode:
|
||||||
assert not args.code
|
assert not args.code
|
||||||
args.code = "0-"
|
args.code = u"0-"
|
||||||
code = args.code
|
code = args.code
|
||||||
if not code:
|
if not code:
|
||||||
code = w.input_code("Enter receive wormhole code: ", args.code_length)
|
code = w.input_code("Enter receive wormhole code: ", args.code_length)
|
||||||
|
|
|
@ -46,7 +46,7 @@ def send(args):
|
||||||
w = Wormhole(APPID, args.relay_url)
|
w = Wormhole(APPID, args.relay_url)
|
||||||
if args.zeromode:
|
if args.zeromode:
|
||||||
assert not args.code
|
assert not args.code
|
||||||
args.code = "0-"
|
args.code = u"0-"
|
||||||
if args.code:
|
if args.code:
|
||||||
w.set_code(args.code)
|
w.set_code(args.code)
|
||||||
code = args.code
|
code = args.code
|
||||||
|
|
|
@ -69,7 +69,8 @@ p = subparsers.add_parser("send",
|
||||||
usage="wormhole send [FILENAME]")
|
usage="wormhole send [FILENAME]")
|
||||||
p.add_argument("--text", metavar="MESSAGE",
|
p.add_argument("--text", metavar="MESSAGE",
|
||||||
help="text message to send, instead of a file")
|
help="text message to send, instead of a file")
|
||||||
p.add_argument("--code", metavar="CODE", help="human-generated code phrase")
|
p.add_argument("--code", metavar="CODE", help="human-generated code phrase",
|
||||||
|
type=type(u""))
|
||||||
p.add_argument("-0", dest="zeromode", action="store_true",
|
p.add_argument("-0", dest="zeromode", action="store_true",
|
||||||
help="enable no-code anything-goes mode")
|
help="enable no-code anything-goes mode")
|
||||||
p.add_argument("what", nargs="?", default=None, metavar="[FILENAME]",
|
p.add_argument("what", nargs="?", default=None, metavar="[FILENAME]",
|
||||||
|
@ -95,6 +96,7 @@ p.add_argument("code", nargs="?", default=None, metavar="[CODE]",
|
||||||
help=dedent("""\
|
help=dedent("""\
|
||||||
The magic-wormhole code, from the sender. If omitted, the
|
The magic-wormhole code, from the sender. If omitted, the
|
||||||
program will ask for it, using tab-completion."""),
|
program will ask for it, using tab-completion."""),
|
||||||
|
type=type(u""),
|
||||||
)
|
)
|
||||||
p.set_defaults(func=cmd_receive.receive)
|
p.set_defaults(func=cmd_receive.receive)
|
||||||
|
|
||||||
|
|
|
@ -140,8 +140,8 @@ class Blocking(ServerBase, unittest.TestCase):
|
||||||
def test_fixed_code(self):
|
def test_fixed_code(self):
|
||||||
w1 = BlockingWormhole(APPID, self.relayurl)
|
w1 = BlockingWormhole(APPID, self.relayurl)
|
||||||
w2 = BlockingWormhole(APPID, self.relayurl)
|
w2 = BlockingWormhole(APPID, self.relayurl)
|
||||||
w1.set_code("123-purple-elephant")
|
w1.set_code(u"123-purple-elephant")
|
||||||
w2.set_code("123-purple-elephant")
|
w2.set_code(u"123-purple-elephant")
|
||||||
d = self.doBoth([w1.send_data, b"data1"], [w2.send_data, b"data2"])
|
d = self.doBoth([w1.send_data, b"data1"], [w2.send_data, b"data2"])
|
||||||
def _sent(res):
|
def _sent(res):
|
||||||
return self.doBoth([w1.get_data], [w2.get_data])
|
return self.doBoth([w1.get_data], [w2.get_data])
|
||||||
|
@ -201,7 +201,7 @@ class Blocking(ServerBase, unittest.TestCase):
|
||||||
self.assertRaises(UsageError, w1.get_verifier)
|
self.assertRaises(UsageError, w1.get_verifier)
|
||||||
self.assertRaises(UsageError, w1.get_data)
|
self.assertRaises(UsageError, w1.get_data)
|
||||||
self.assertRaises(UsageError, w1.send_data, b"data")
|
self.assertRaises(UsageError, w1.send_data, b"data")
|
||||||
w1.set_code("123-purple-elephant")
|
w1.set_code(u"123-purple-elephant")
|
||||||
self.assertRaises(UsageError, w1.set_code, "123-nope")
|
self.assertRaises(UsageError, w1.set_code, "123-nope")
|
||||||
self.assertRaises(UsageError, w1.get_code)
|
self.assertRaises(UsageError, w1.get_code)
|
||||||
w2 = BlockingWormhole(APPID, self.relayurl)
|
w2 = BlockingWormhole(APPID, self.relayurl)
|
||||||
|
|
|
@ -82,7 +82,7 @@ class Scripts(ServerBase, ScriptsBase, unittest.TestCase):
|
||||||
def test_send_text_pre_generated_code(self):
|
def test_send_text_pre_generated_code(self):
|
||||||
wormhole = self.find_executable()
|
wormhole = self.find_executable()
|
||||||
server_args = ["--relay-url", self.relayurl]
|
server_args = ["--relay-url", self.relayurl]
|
||||||
code = "1-abc"
|
code = u"1-abc"
|
||||||
message = "test message"
|
message = "test message"
|
||||||
send_args = server_args + [
|
send_args = server_args + [
|
||||||
"send",
|
"send",
|
||||||
|
@ -120,7 +120,7 @@ class Scripts(ServerBase, ScriptsBase, unittest.TestCase):
|
||||||
|
|
||||||
def test_send_file_pre_generated_code(self):
|
def test_send_file_pre_generated_code(self):
|
||||||
self.maxDiff=None
|
self.maxDiff=None
|
||||||
code = "1-abc"
|
code = u"1-abc"
|
||||||
filename = "testfile"
|
filename = "testfile"
|
||||||
message = "test message"
|
message = "test message"
|
||||||
|
|
||||||
|
|
|
@ -128,8 +128,8 @@ class Basic(ServerBase, unittest.TestCase):
|
||||||
def test_fixed_code(self):
|
def test_fixed_code(self):
|
||||||
w1 = Wormhole(APPID, self.relayurl)
|
w1 = Wormhole(APPID, self.relayurl)
|
||||||
w2 = Wormhole(APPID, self.relayurl)
|
w2 = Wormhole(APPID, self.relayurl)
|
||||||
w1.set_code("123-purple-elephant")
|
w1.set_code(u"123-purple-elephant")
|
||||||
w2.set_code("123-purple-elephant")
|
w2.set_code(u"123-purple-elephant")
|
||||||
d = self.doBoth(w1.send_data(b"data1"), w2.send_data(b"data2"))
|
d = self.doBoth(w1.send_data(b"data1"), w2.send_data(b"data2"))
|
||||||
def _sent(res):
|
def _sent(res):
|
||||||
return self.doBoth(w1.get_data(), w2.get_data())
|
return self.doBoth(w1.get_data(), w2.get_data())
|
||||||
|
@ -188,7 +188,7 @@ class Basic(ServerBase, unittest.TestCase):
|
||||||
self.assertRaises(UsageError, w1.get_verifier)
|
self.assertRaises(UsageError, w1.get_verifier)
|
||||||
self.assertRaises(UsageError, w1.send_data, b"data")
|
self.assertRaises(UsageError, w1.send_data, b"data")
|
||||||
self.assertRaises(UsageError, w1.get_data)
|
self.assertRaises(UsageError, w1.get_data)
|
||||||
w1.set_code("123-purple-elephant")
|
w1.set_code(u"123-purple-elephant")
|
||||||
self.assertRaises(UsageError, w1.set_code, "123-nope")
|
self.assertRaises(UsageError, w1.set_code, "123-nope")
|
||||||
self.assertRaises(UsageError, w1.get_code)
|
self.assertRaises(UsageError, w1.get_code)
|
||||||
w2 = Wormhole(APPID, self.relayurl)
|
w2 = Wormhole(APPID, self.relayurl)
|
||||||
|
|
|
@ -223,7 +223,7 @@ class Wormhole:
|
||||||
d = self._channel_manager.allocate()
|
d = self._channel_manager.allocate()
|
||||||
def _got_channelid(channelid):
|
def _got_channelid(channelid):
|
||||||
code = codes.make_code(channelid, code_length)
|
code = codes.make_code(channelid, code_length)
|
||||||
assert isinstance(code, str), type(code)
|
assert isinstance(code, type(u"")), type(code)
|
||||||
self._set_code_and_channelid(code)
|
self._set_code_and_channelid(code)
|
||||||
self._start()
|
self._start()
|
||||||
return code
|
return code
|
||||||
|
@ -231,7 +231,7 @@ class Wormhole:
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def set_code(self, code):
|
def set_code(self, code):
|
||||||
if not isinstance(code, str): raise UsageError
|
if not isinstance(code, type(u"")): raise UsageError
|
||||||
if self.code is not None: raise UsageError
|
if self.code is not None: raise UsageError
|
||||||
self._set_code_and_channelid(code)
|
self._set_code_and_channelid(code)
|
||||||
self._start()
|
self._start()
|
||||||
|
@ -248,7 +248,7 @@ class Wormhole:
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
# allocate the rest now too, so it can be serialized
|
# allocate the rest now too, so it can be serialized
|
||||||
self.sp = SPAKE2_Symmetric(self.code.encode("ascii"),
|
self.sp = SPAKE2_Symmetric(to_bytes(self.code),
|
||||||
idSymmetric=to_bytes(self._appid))
|
idSymmetric=to_bytes(self._appid))
|
||||||
self.msg1 = self.sp.start()
|
self.msg1 = self.sp.start()
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ class Wormhole:
|
||||||
d = json.loads(data)
|
d = json.loads(data)
|
||||||
self = klass(d["appid"], d["relay_url"])
|
self = klass(d["appid"], d["relay_url"])
|
||||||
self._set_side(d["side"].encode("ascii"))
|
self._set_side(d["side"].encode("ascii"))
|
||||||
self._set_code_and_channelid(d["code"].encode("ascii"))
|
self._set_code_and_channelid(d["code"])
|
||||||
self.sp = SPAKE2_Symmetric.from_serialized(json.dumps(d["spake2"]))
|
self.sp = SPAKE2_Symmetric.from_serialized(json.dumps(d["spake2"]))
|
||||||
self.msg1 = d["msg1"].decode("hex")
|
self.msg1 = d["msg1"].decode("hex")
|
||||||
return self
|
return self
|
||||||
|
|
Loading…
Reference in New Issue
Block a user