def build_pake(self, code):
     with self._timing.add("pake1", waiting="crypto"):
         self._sp = SPAKE2_Symmetric(to_bytes(code),
                                     idSymmetric=to_bytes(self._appid))
         msg1 = self._sp.start()
     body = dict_to_bytes({"pake_v1": bytes_to_hexstr(msg1)})
     self._M.add_message("pake", body)
示例#2
0
    def test_reversed(self):
        # A receiver using input_code() will choose the nameplate first, then
        # the rest of the code. Once the nameplate is selected, we'll claim
        # it and open the mailbox, which will cause the senders PAKE to
        # arrive before the code has been set. Key() is supposed to stash the
        # PAKE message until the code is set (allowing the PAKE computation
        # to finish). This test exercises that PAKE-then-code sequence.
        k, b, m, r, events = self.build()
        code = u"1-foo"

        sp = SPAKE2_Symmetric(to_bytes(code), idSymmetric=to_bytes(u"appid"))
        msg2_bytes = sp.start()
        msg2 = dict_to_bytes({"pake_v1": bytes_to_hexstr(msg2_bytes)})
        k.got_pake(msg2)
        self.assertEqual(len(events), 0)

        k.got_code(code)
        self.assertEqual(len(events), 4)
        self.assertEqual(events[0][:2], ("m.add_message", "pake"))
        msg1_json = events[0][2].decode("utf-8")
        msg1 = json.loads(msg1_json)
        msg1_bytes = hexstr_to_bytes(msg1["pake_v1"])
        key2 = sp.finish(msg1_bytes)
        self.assertEqual(events[1], ("b.got_key", key2))
        self.assertEqual(events[2][:2], ("m.add_message", "version"))
        self.assertEqual(events[3], ("r.got_key", key2))
def run_exchange(transport, code, app_id, side):
    # Send the SPAKE2 message
    spake = SPAKE2_Symmetric(util.to_bytes(code),
                             idSymmetric=util.to_bytes(app_id))
    outbound = spake.start()
    transport.send_json({
        'phase':
        u'pake',
        'body':
        util.bytes_to_hexstr(
            util.dict_to_bytes({
                'pake_v1': util.bytes_to_hexstr(outbound),
            })),
        'side':
        side,
        'type':
        'message',
    })

    # Receive SPAKE2 message
    pake_msg = transport.receive_json()
    inbound = util.hexstr_to_bytes(
        util.bytes_to_dict(util.hexstr_to_bytes(pake_msg['body']))['pake_v1'])
    spake_key = spake.finish(inbound)
    transport.send_line(util.bytes_to_hexstr(spake_key))
示例#4
0
 def from_serialized(klass, data):
     d = json.loads(data)
     self = klass(d["appid"].encode("ascii"), d["relay"].encode("ascii"))
     self._set_code_and_channel_id(d["code"].encode("ascii"))
     self.side = d["side"].encode("ascii")
     self.sp = SPAKE2_Symmetric.from_serialized(json.dumps(d["spake2"]))
     self.msg1 = d["msg1"].decode("hex")
     return self
示例#5
0
 def from_serialized(klass, data):
     d = json.loads(data)
     self = klass(d["appid"].encode("ascii"), d["relay"].encode("ascii"))
     self._set_code_and_channel_id(d["code"].encode("ascii"))
     self.side = d["side"].encode("ascii")
     self.sp = SPAKE2_Symmetric.from_serialized(json.dumps(d["spake2"]))
     self.msg1 = d["msg1"].decode("hex")
     return self
示例#6
0
 def _maybe_build_msg1(self):
     if not (self._code and self._flag_need_to_build_msg1):
         return
     with self._timing.add("pake1", waiting="crypto"):
         self._sp = SPAKE2_Symmetric(to_bytes(self._code),
                                     idSymmetric=to_bytes(self._appid))
         self._msg1 = self._sp.start()
     self._flag_need_to_build_msg1 = False
     self._event_built_msg1()
示例#7
0
 def from_serialized(klass, data):
     d = json.loads(data)
     self = klass(d["appid"], d["relay_url"])
     self._side = d["side"]
     self._channelid = d["channelid"]
     self._set_code(d["code"])
     sp_data = json.dumps(d["spake2"]).encode("ascii")
     self._sp = SPAKE2_Symmetric.from_serialized(sp_data)
     self._msg1 = unhexlify(d["msg1"].encode("ascii"))
     return self
示例#8
0
def get_protocol(code, side, side_id, other_side_id):
    code = code.encode('utf8')
    side_id = side_id.encode('utf8')
    if side == 'S':
        return SPAKE2_Symmetric(code, idSymmetric=side_id)
    other_side_id = other_side_id.encode('utf8')
    if side == 'A':
        return SPAKE2_A(code, idA=side_id, idB=other_side_id)
    elif side == 'B':
        return SPAKE2_B(code, idA=other_side_id, idB=side_id)
    else:
        raise AssertionError('Invalid side: %r' % (side, ))
示例#9
0
    def test_version_error(self):
        # we should only receive the "version" message after we receive the
        # PAKE message, by which point we should know the key. If the
        # confirmation message doesn't decrypt, we signal an error.
        timing = DebugTiming()
        w = wormhole._Wormhole(APPID, "relay_url", reactor, None, timing)
        w._drop_connection = mock.Mock()
        ws = MockWebSocket()
        w._event_connected(ws)
        w._event_ws_opened(None)
        w.set_code("123-foo-bar")
        response(w, type="claimed", mailbox="mb456")

        d1 = w.get()
        d2 = w.verify()
        self.assertNoResult(d1)
        self.assertNoResult(d2)

        out = ws.outbound()
        # ["bind", "claim", "open", "add"]
        self.assertEqual(len(out), 4)
        self.assertEqual(out[3]["type"], "add")

        sp2 = SPAKE2_Symmetric(b"", idSymmetric=wormhole.to_bytes(APPID))
        msg2 = sp2.start()
        payload = {"pake_v1": bytes_to_hexstr(msg2)}
        body_hex = bytes_to_hexstr(dict_to_bytes(payload))
        response(w, type="message", phase="pake", body=body_hex, side="s2")
        self.assertNoResult(d1)
        self.assertNoResult(d2)  # verify() waits for confirmation

        # sending a random version message will cause a confirmation error
        confkey = w.derive_key("WRONG", SecretBox.KEY_SIZE)
        nonce = os.urandom(wormhole.CONFMSG_NONCE_LENGTH)
        badversion = wormhole.make_confmsg(confkey, nonce)
        badversion_hex = hexlify(badversion).decode("ascii")
        response(w,
                 type="message",
                 phase="version",
                 body=badversion_hex,
                 side="s2")

        self.failureResultOf(d1, WrongPasswordError)
        self.failureResultOf(d2, WrongPasswordError)

        # once the error is signalled, all API calls should fail
        self.assertRaises(WrongPasswordError, w.send, "foo")
        self.assertRaises(WrongPasswordError, w.derive_key, "foo",
                          SecretBox.KEY_SIZE)
        self.failureResultOf(w.get(), WrongPasswordError)
        self.failureResultOf(w.verify(), WrongPasswordError)
示例#10
0
def run_exchange(transport, code, app_id, side):
    # Send the SPAKE2 message
    spake = SPAKE2_Symmetric(
        util.to_bytes(code), idSymmetric=util.to_bytes(app_id))
    outbound = spake.start()
    transport.send_json({
        'phase': 'pake',
        'body': util.bytes_to_hexstr(
            util.dict_to_bytes({
                'pake_v1': util.bytes_to_hexstr(outbound),
            })
        ),
        'side': side,
        'type': 'message',
    })

    # Receive SPAKE2 message
    pake_msg = transport.receive_json()
    inbound = util.hexstr_to_bytes(
        util.bytes_to_dict(
            util.hexstr_to_bytes(pake_msg['body'])
        )['pake_v1']
    )
    spake_key = spake.finish(inbound)

    # Send the versions message
    version_phase = 'version'
    transport.send_json({
        'phase': version_phase,
        'body': util.bytes_to_hexstr(
            encrypt_data(
                derive_phase_key(spake_key, side, version_phase),
                util.dict_to_bytes({'app_versions': {}})
            )
        ),
        'side': side,
        'type': 'message',
    })

    # Receive the versions message
    versions = transport.receive_json()
    their_versions = util.bytes_to_dict(
        decrypt_data(
            derive_phase_key(spake_key, versions['side'], versions['phase']),
            util.hexstr_to_bytes(
                versions['body']
            ),
        ),
    )
    return their_versions
示例#11
0
 def test_good(self):
     k, b, m, r, events = self.build()
     code = u"1-foo"
     k.got_code(code)
     self.assertEqual(len(events), 1)
     self.assertEqual(events[0][:2], ("m.add_message", "pake"))
     msg1_json = events[0][2].decode("utf-8")
     events[:] = []
     msg1 = json.loads(msg1_json)
     msg1_bytes = hexstr_to_bytes(msg1["pake_v1"])
     sp = SPAKE2_Symmetric(to_bytes(code), idSymmetric=to_bytes(u"appid"))
     msg2_bytes = sp.start()
     key2 = sp.finish(msg1_bytes)
     msg2 = dict_to_bytes({"pake_v1": bytes_to_hexstr(msg2_bytes)})
     k.got_pake(msg2)
     self.assertEqual(len(events), 3, events)
     self.assertEqual(events[0], ("b.got_key", key2))
     self.assertEqual(events[1][:2], ("m.add_message", "version"))
     self.assertEqual(events[2], ("r.got_key", key2))
示例#12
0
 def _start(self):
     # allocate the rest now too, so it can be serialized
     self.sp = SPAKE2_Symmetric(to_bytes(self.code),
                                idSymmetric=to_bytes(self._appid))
     self.msg1 = self.sp.start()
示例#13
0
 def make_pake(self, code, side, msg1):
     sp2 = SPAKE2_Symmetric(wormhole.to_bytes(code),
                            idSymmetric=wormhole.to_bytes(APPID))
     msg2 = sp2.start()
     key = sp2.finish(msg1)
     return key, msg2
示例#14
0
 def _start(self):
     # allocate the rest now too, so it can be serialized
     self.sp = SPAKE2_Symmetric(self.code.encode("ascii"),
                                idA=self.appid + ":SymmetricA",
                                idB=self.appid + ":SymmetricB")
     self.msg1 = self.sp.start()