[noise] Socketguard: seeking feedback on protocol variations

Ben Burkert ben at benburkert.com
Tue Apr 21 15:57:01 PDT 2020


On Tue, Apr 21, 2020 at 12:30:05AM -0700, Trevor Perrin wrote:
> On Sat, Apr 18, 2020 at 10:21 AM Ben Burkert <ben at benburkert.com>
> wrote:
>
> If the version is encrypted it might be hard to use the version to
> change things about the encryption.  If you want to encrypt some
> negotiation data though, couldn't you just put it in the handshake
> payload?

Yes, the handshake's payload for the initial version is the sender's
static key & the version string (both encrypted). And the version string
is two numbers: the minimum and maximum versions the initiator supports,
or for the responder it's the agreed upon version & it's max supported
version.

My thinking is that each version can "allocate" the next N bytes in the
handshake payload that it requires. For example, if version 2 adds
support for a non-Curve25519 key, the (encrypted) public key bytes would
go after the version 1 payload. The responder would ignore the v2 bytes
if it only supports v1.

Assuming all that, then in the future Curve25519 may only be used to
encrypt the version negotiation and bootstrap the "real" handshake. If
Curve25519 is able to be broken in real time, then the protocol could be
MITM'd and should be entirely scrapped. But, in a world where Curve25519
is breakable but prohibitively expensive to MITM, only identity hiding
of the Curve25519 key & versioning info would be compromisable. Losing
identity hiding would be unfortunate but not reason enough to deprecate
the entire protocol.

> > Secondly, rekeying is modified to include an "es" DH exchange to
> > provide
> > ongoing forward-secrecy and key-compromise impersonation resistance.
>
> If you've already got the ability to handshake, and a TCP connection,
> just running the handshake again might be simpler.

A full handshake requires a roundtrip, which would block the sender.
Unfortunately, because the module can't run in between read/write
syscalls, there's no way to perform these handshakes in the background.
And the other side can still send data, so a full handshake might
require the blocked sender to read & buffer data until it gets to the
handshake response, which can more or less break TCP's backpressure
mechanism. And because the other side can't send the handshake response
until it first reads all data prior to the handshake, the stall
introduced by handshakes could be significantly larger than the RTT.

Doing the full handshake was simpler from the Noise side of things, but
really complicated the normal connection plumbing stuff. Keeping the
connection modeled as two unidirectional streams and adapting encryption
protocol seems to be less complex overall.

> Or you could just rely on Noise's "rekey" ability to ratchet the
> encryption keys forward, so a compromise can't decrypt old data.

I'd like to keep the "forward secrecy healing" property that you get
with re-handshaking, because I would like the protocol to be suitable
for long lived TCP connections for clients like NBD or NFS. Is this
achievable with Noise's rekeying?

Thanks for reading & responding!


More information about the Noise mailing list