Previously the encryption key used for "phase messages" (anything sent
from one side to the other, protected by the shared PAKE-generated
session key) was derived just from the session key and the phase name.
The two sides would use the same key for their first message (but with
random, thus different, nonces).
This uses the sending side's string (a random 5-byte/10-character hex
string) in the derivation process too, so the two sides use different
keys. This gives us an easy way to reject reflected messages. We already
ignore messages that claim to use a "side" which matches our own (to
ignore server echoes of our own outbound messages). With this change, an
attacker (or the server) can't swap in the payload of an outbound
message, change the "side" to make it look like a peer message, and then
let us decrypt it correctly.
It also changes the derivation function to combine the phase and side
values safely. This didn't matter much when we only had one
externally-provided string, but with two, there's an opportunity for
format confusion if they were combined with a simple delimiter. Now we
hash both values before concatenating them.
This breaks interoperability with clients from before this change. They
will always get WrongPasswordErrors.
* To avoid an incompatible patch that landed in Twisted trunk after the
16.1.1 release, autobahn pinned their requirement on Twisted to
be <=16.1.1 . However Twisted reverted the patch before making a
release. The new 16.2.0 is fine. Since autobahn has this pin, and
since pip doesn't do full dependency resolution, I must add the pin
too, so that 'pip install magic-wormhole' can work. I plan to remove
this pin as soon as autobahn does the same upstream.
https://github.com/crossbario/autobahn-python/issues/680
* A previous version of autobahn had a bug where it tried to import
something that wasn't actually depended upon, exposed by having pynacl
installed. Installing 'pytrie' manually fixed it. This doesn't seem to
be a problem anymore, so I'm removing the manual dependency.
* add "released" ack-response for "release" command, to sync w.close()
* move websocket URL to root
* relayurl= should now be a "ws://" URL
* many tests pass (except for test_twisted, which will be removed, and
test_scripts)
* still moving integration tests from test_twisted to
test_wormhole.Wormholes
This made sense for ServerSentEvent channels (which has no purpose once
the channel was gone), but not so much for websockets. And it prevented
testing duplicate-close.
Pass in a handle and a pair of functions, rather than an object with two
well-known methods. This should make it easier to subscribe to multiple
channels in the future.