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
 | 
			
		||||
techniques.
 | 
			
		||||
 | 
			
		||||
Note that the code is a human-readable string (the python "str" type: so
 | 
			
		||||
unicode in python3, plain bytes in python2).
 | 
			
		||||
Note that the code is a human-readable string (the python "unicode" type in
 | 
			
		||||
python2, "str" in python3).
 | 
			
		||||
 | 
			
		||||
## Application Identifier
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -248,13 +248,10 @@ python2, "bytes" in python3):
 | 
			
		|||
* data in/out
 | 
			
		||||
* transit records in/out
 | 
			
		||||
 | 
			
		||||
Some human-readable parameters are passed as strings: "str" in python2, "str"
 | 
			
		||||
(i.e. unicode) in python3:
 | 
			
		||||
Other (human-facing) values are always unicode ("unicode" in python2, "str"
 | 
			
		||||
in python3):
 | 
			
		||||
 | 
			
		||||
* wormhole code
 | 
			
		||||
 | 
			
		||||
And some are always unicode, in both python2 and python3:
 | 
			
		||||
 | 
			
		||||
* relay URL
 | 
			
		||||
* transit URLs
 | 
			
		||||
* transit connection hints (e.g. "host:port")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -186,7 +186,7 @@ class Wormhole:
 | 
			
		|||
        if self.code is not None: raise UsageError
 | 
			
		||||
        channelid = self._channel_manager.allocate()
 | 
			
		||||
        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._start()
 | 
			
		||||
        return code
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ class Wormhole:
 | 
			
		|||
        return code
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        self._set_code_and_channelid(code)
 | 
			
		||||
        self._start()
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +215,7 @@ class Wormhole:
 | 
			
		|||
 | 
			
		||||
    def _start(self):
 | 
			
		||||
        # 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))
 | 
			
		||||
        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())
 | 
			
		||||
        else:
 | 
			
		||||
            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):
 | 
			
		||||
    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_delims("")
 | 
			
		||||
    code = six.moves.input(prompt)
 | 
			
		||||
    return code
 | 
			
		||||
    return code.decode("utf-8")
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    code = input_code_with_completion("Enter wormhole code: ", lambda: [], 2)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ def receive(args):
 | 
			
		|||
    w = Wormhole(APPID, args.relay_url)
 | 
			
		||||
    if args.zeromode:
 | 
			
		||||
        assert not args.code
 | 
			
		||||
        args.code = "0-"
 | 
			
		||||
        args.code = u"0-"
 | 
			
		||||
    code = args.code
 | 
			
		||||
    if not code:
 | 
			
		||||
        code = w.input_code("Enter receive wormhole code: ", args.code_length)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ def send(args):
 | 
			
		|||
    w = Wormhole(APPID, args.relay_url)
 | 
			
		||||
    if args.zeromode:
 | 
			
		||||
        assert not args.code
 | 
			
		||||
        args.code = "0-"
 | 
			
		||||
        args.code = u"0-"
 | 
			
		||||
    if args.code:
 | 
			
		||||
        w.set_code(args.code)
 | 
			
		||||
        code = args.code
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,8 @@ p = subparsers.add_parser("send",
 | 
			
		|||
                          usage="wormhole send [FILENAME]")
 | 
			
		||||
p.add_argument("--text", metavar="MESSAGE",
 | 
			
		||||
               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",
 | 
			
		||||
               help="enable no-code anything-goes mode")
 | 
			
		||||
p.add_argument("what", nargs="?", default=None, metavar="[FILENAME]",
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +96,7 @@ p.add_argument("code", nargs="?", default=None, metavar="[CODE]",
 | 
			
		|||
               help=dedent("""\
 | 
			
		||||
               The magic-wormhole code, from the sender. If omitted, the
 | 
			
		||||
               program will ask for it, using tab-completion."""),
 | 
			
		||||
               type=type(u""),
 | 
			
		||||
               )
 | 
			
		||||
p.set_defaults(func=cmd_receive.receive)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,8 +140,8 @@ class Blocking(ServerBase, unittest.TestCase):
 | 
			
		|||
    def test_fixed_code(self):
 | 
			
		||||
        w1 = BlockingWormhole(APPID, self.relayurl)
 | 
			
		||||
        w2 = BlockingWormhole(APPID, self.relayurl)
 | 
			
		||||
        w1.set_code("123-purple-elephant")
 | 
			
		||||
        w2.set_code("123-purple-elephant")
 | 
			
		||||
        w1.set_code(u"123-purple-elephant")
 | 
			
		||||
        w2.set_code(u"123-purple-elephant")
 | 
			
		||||
        d = self.doBoth([w1.send_data, b"data1"], [w2.send_data, b"data2"])
 | 
			
		||||
        def _sent(res):
 | 
			
		||||
            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_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.get_code)
 | 
			
		||||
        w2 = BlockingWormhole(APPID, self.relayurl)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ class Scripts(ServerBase, ScriptsBase, unittest.TestCase):
 | 
			
		|||
    def test_send_text_pre_generated_code(self):
 | 
			
		||||
        wormhole = self.find_executable()
 | 
			
		||||
        server_args = ["--relay-url", self.relayurl]
 | 
			
		||||
        code = "1-abc"
 | 
			
		||||
        code = u"1-abc"
 | 
			
		||||
        message = "test message"
 | 
			
		||||
        send_args = server_args + [
 | 
			
		||||
            "send",
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ class Scripts(ServerBase, ScriptsBase, unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_send_file_pre_generated_code(self):
 | 
			
		||||
        self.maxDiff=None
 | 
			
		||||
        code = "1-abc"
 | 
			
		||||
        code = u"1-abc"
 | 
			
		||||
        filename = "testfile"
 | 
			
		||||
        message = "test message"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,8 +128,8 @@ class Basic(ServerBase, unittest.TestCase):
 | 
			
		|||
    def test_fixed_code(self):
 | 
			
		||||
        w1 = Wormhole(APPID, self.relayurl)
 | 
			
		||||
        w2 = Wormhole(APPID, self.relayurl)
 | 
			
		||||
        w1.set_code("123-purple-elephant")
 | 
			
		||||
        w2.set_code("123-purple-elephant")
 | 
			
		||||
        w1.set_code(u"123-purple-elephant")
 | 
			
		||||
        w2.set_code(u"123-purple-elephant")
 | 
			
		||||
        d = self.doBoth(w1.send_data(b"data1"), w2.send_data(b"data2"))
 | 
			
		||||
        def _sent(res):
 | 
			
		||||
            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.send_data, b"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.get_code)
 | 
			
		||||
        w2 = Wormhole(APPID, self.relayurl)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -223,7 +223,7 @@ class Wormhole:
 | 
			
		|||
        d = self._channel_manager.allocate()
 | 
			
		||||
        def _got_channelid(channelid):
 | 
			
		||||
            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._start()
 | 
			
		||||
            return code
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ class Wormhole:
 | 
			
		|||
        return d
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        self._set_code_and_channelid(code)
 | 
			
		||||
        self._start()
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ class Wormhole:
 | 
			
		|||
 | 
			
		||||
    def _start(self):
 | 
			
		||||
        # 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))
 | 
			
		||||
        self.msg1 = self.sp.start()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +274,7 @@ class Wormhole:
 | 
			
		|||
        d = json.loads(data)
 | 
			
		||||
        self = klass(d["appid"], d["relay_url"])
 | 
			
		||||
        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.msg1 = d["msg1"].decode("hex")
 | 
			
		||||
        return self
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user