implement w.derive_key()
This commit is contained in:
parent
0474c39bab
commit
60a61c995b
|
@ -63,7 +63,7 @@ digraph {
|
|||
|
||||
{rank=same; Other S_closed}
|
||||
Other [shape="box" style="dashed"
|
||||
label="rx_welcome -> process\nsend -> S.send\ngot_verifier -> W.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code"
|
||||
label="rx_welcome -> process\nsend -> S.send\ngot_key -> W.got_key\ngot_verifier -> W.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code"
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ digraph {
|
|||
S1 -> P1_compute [label="got_pake\npake good"]
|
||||
#S1 -> P_mood_lonely [label="close"]
|
||||
|
||||
P1_compute [label="compute_key\nM.add_message(version)\nW.got_verifier\nR.got_key" shape="box"]
|
||||
P1_compute [label="compute_key\nM.add_message(version)\nB.got_key\nB.got_verifier\nR.got_key" shape="box"]
|
||||
P1_compute -> S2
|
||||
|
||||
S2 [label="S2: know_key" color="green"]
|
||||
|
|
|
@ -21,7 +21,7 @@ digraph {
|
|||
|
||||
Wormhole -> Boss [style="dashed" label="allocate_code\ninput_code\nset_code\nsend\nclose\n(once)"]
|
||||
#Wormhole -> Boss [color="blue"]
|
||||
Boss -> Wormhole [style="dashed" label="got_code\ngot_verifier\nreceived (seq)\nclosed\n(once)"]
|
||||
Boss -> Wormhole [style="dashed" label="got_code\ngot_key\ngot_verifier\nreceived (seq)\nclosed\n(once)"]
|
||||
|
||||
#Boss -> Connection [color="blue"]
|
||||
Boss -> Connection [style="dashed" label="start"]
|
||||
|
@ -33,7 +33,7 @@ digraph {
|
|||
#Boss -> Mailbox [color="blue"]
|
||||
Mailbox -> Order [style="dashed" label="got_message (once)"]
|
||||
Boss -> Key [style="dashed" label="got_code"]
|
||||
Key -> Boss [style="dashed" label="got_verifier\nscared"]
|
||||
Key -> Boss [style="dashed" label="got_key\ngot_verifier\nscared"]
|
||||
Order -> Key [style="dashed" label="got_pake"]
|
||||
Order -> Receive [style="dashed" label="got_message"]
|
||||
#Boss -> Key [color="blue"]
|
||||
|
|
|
@ -135,7 +135,7 @@ class Boss(object):
|
|||
@m.input()
|
||||
def got_code(self, code): pass
|
||||
|
||||
# Key sends (got_verifier, scared)
|
||||
# Key sends (got_key, got_verifier, scared)
|
||||
# Receive sends (got_message, happy, scared)
|
||||
@m.input()
|
||||
def happy(self): pass
|
||||
|
@ -158,6 +158,8 @@ class Boss(object):
|
|||
@m.input()
|
||||
def got_phase(self, phase, plaintext): pass
|
||||
@m.input()
|
||||
def got_key(self, key): pass
|
||||
@m.input()
|
||||
def got_verifier(self, verifier): pass
|
||||
|
||||
# Terminator sends closed
|
||||
|
@ -205,6 +207,9 @@ class Boss(object):
|
|||
self._T.close("happy")
|
||||
|
||||
@m.output()
|
||||
def W_got_key(self, key):
|
||||
self._W.got_key(key)
|
||||
@m.output()
|
||||
def W_got_verifier(self, verifier):
|
||||
self._W.got_verifier(verifier)
|
||||
@m.output()
|
||||
|
@ -238,6 +243,7 @@ class Boss(object):
|
|||
S1_lonely.upon(scared, enter=S3_closing, outputs=[close_scared])
|
||||
S1_lonely.upon(close, enter=S3_closing, outputs=[close_lonely])
|
||||
S1_lonely.upon(send, enter=S1_lonely, outputs=[S_send])
|
||||
S1_lonely.upon(got_key, enter=S1_lonely, outputs=[W_got_key])
|
||||
S1_lonely.upon(got_verifier, enter=S1_lonely, outputs=[W_got_verifier])
|
||||
S1_lonely.upon(rx_error, enter=S3_closing, outputs=[close_error])
|
||||
S1_lonely.upon(error, enter=S4_closed, outputs=[W_close_with_error])
|
||||
|
|
|
@ -110,6 +110,7 @@ class Key(object):
|
|||
assert isinstance(msg2, type(b""))
|
||||
with self._timing.add("pake2", waiting="crypto"):
|
||||
key = self._sp.finish(msg2)
|
||||
self._B.got_key(key)
|
||||
self._B.got_verifier(derive_key(key, b"wormhole:verifier"))
|
||||
phase = "version"
|
||||
data_key = derive_phase_key(key, self._side, phase)
|
||||
|
|
|
@ -50,3 +50,6 @@ class TransferError(WormholeError):
|
|||
|
||||
class NoTorError(WormholeError):
|
||||
"""--tor was requested, but 'txtorcon' is not installed."""
|
||||
|
||||
class NoKeyError(WormholeError):
|
||||
"""w.derive_key() was called before got_verifier() fired"""
|
||||
|
|
|
@ -147,7 +147,7 @@ class Key(unittest.TestCase):
|
|||
def build(self):
|
||||
events = []
|
||||
k = _key.Key(u"appid", u"side", timing.DebugTiming())
|
||||
b = Dummy("b", events, IBoss, "scared", "got_verifier")
|
||||
b = Dummy("b", events, IBoss, "scared", "got_key", "got_verifier")
|
||||
m = Dummy("m", events, IMailbox, "add_message")
|
||||
r = Dummy("r", events, IReceive, "got_key")
|
||||
k.wire(b, m, r)
|
||||
|
@ -168,10 +168,11 @@ class Key(unittest.TestCase):
|
|||
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)
|
||||
self.assertEqual(events[0][0], "b.got_verifier")
|
||||
self.assertEqual(events[1][:2], ("m.add_message", "version"))
|
||||
self.assertEqual(events[2], ("r.got_key", key2))
|
||||
self.assertEqual(len(events), 4, events)
|
||||
self.assertEqual(events[0], ("b.got_key", key2))
|
||||
self.assertEqual(events[1][0], "b.got_verifier")
|
||||
self.assertEqual(events[2][:2], ("m.add_message", "version"))
|
||||
self.assertEqual(events[3], ("r.got_key", key2))
|
||||
|
||||
|
||||
def test_bad(self):
|
||||
|
|
|
@ -9,6 +9,9 @@ from .util import bytes_to_hexstr
|
|||
from .timing import DebugTiming
|
||||
from .journal import ImmediateJournal
|
||||
from ._boss import Boss
|
||||
from ._key import derive_key
|
||||
from .errors import NoKeyError
|
||||
from .util import to_bytes
|
||||
|
||||
# We can provide different APIs to different apps:
|
||||
# * Deferreds
|
||||
|
@ -39,6 +42,9 @@ def _log(client_name, machine_name, old_state, input, new_state):
|
|||
class _DelegatedWormhole(object):
|
||||
_delegate = attrib()
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self._key = None
|
||||
|
||||
def _set_boss(self, boss):
|
||||
self._boss = boss
|
||||
|
||||
|
@ -59,6 +65,18 @@ class _DelegatedWormhole(object):
|
|||
|
||||
def send(self, plaintext):
|
||||
self._boss.send(plaintext)
|
||||
|
||||
def derive_key(self, purpose, length):
|
||||
"""Derive a new key from the established wormhole channel for some
|
||||
other purpose. This is a deterministic randomized function of the
|
||||
session key and the 'purpose' string (unicode/py3-string). This
|
||||
cannot be called until when_verifier() has fired, nor after close()
|
||||
was called.
|
||||
"""
|
||||
if not isinstance(purpose, type("")): raise TypeError(type(purpose))
|
||||
if not self._key: raise NoKeyError()
|
||||
return derive_key(self._key, to_bytes(purpose), length)
|
||||
|
||||
def close(self):
|
||||
self._boss.close()
|
||||
|
||||
|
@ -69,6 +87,8 @@ class _DelegatedWormhole(object):
|
|||
# from below
|
||||
def got_code(self, code):
|
||||
self._delegate.wormhole_got_code(code)
|
||||
def got_key(self, key):
|
||||
self._key = key # for derive_key()
|
||||
def got_verifier(self, verifier):
|
||||
self._delegate.wormhole_got_verifier(verifier)
|
||||
def received(self, plaintext):
|
||||
|
@ -84,6 +104,7 @@ class _DeferredWormhole(object):
|
|||
def __init__(self):
|
||||
self._code = None
|
||||
self._code_observers = []
|
||||
self._key = None
|
||||
self._verifier = None
|
||||
self._verifier_observers = []
|
||||
self._received_data = []
|
||||
|
@ -125,6 +146,18 @@ class _DeferredWormhole(object):
|
|||
# no .serialize in Deferred-mode
|
||||
def send(self, plaintext):
|
||||
self._boss.send(plaintext)
|
||||
|
||||
def derive_key(self, purpose, length):
|
||||
"""Derive a new key from the established wormhole channel for some
|
||||
other purpose. This is a deterministic randomized function of the
|
||||
session key and the 'purpose' string (unicode/py3-string). This
|
||||
cannot be called until when_verifier() has fired, nor after close()
|
||||
was called.
|
||||
"""
|
||||
if not isinstance(purpose, type("")): raise TypeError(type(purpose))
|
||||
if not self._key: raise NoKeyError()
|
||||
return derive_key(self._key, to_bytes(purpose), length)
|
||||
|
||||
def close(self):
|
||||
# fails with WormholeError unless we established a connection
|
||||
# (state=="happy"). Fails with WrongPasswordError (a subclass of
|
||||
|
@ -144,6 +177,8 @@ class _DeferredWormhole(object):
|
|||
for d in self._code_observers:
|
||||
d.callback(code)
|
||||
self._code_observers[:] = []
|
||||
def got_key(self, key):
|
||||
self._key = key # for derive_key()
|
||||
def got_verifier(self, verifier):
|
||||
self._verifier = verifier
|
||||
for d in self._verifier_observers:
|
||||
|
|
Loading…
Reference in New Issue
Block a user