[noise] Alice and Bob (was Re: NoiseSocket and "reversed" protocols)

Trevor Perrin trevp at trevp.net
Wed Nov 8 19:29:34 PST 2017

On Fri, Sep 29, 2017 at 2:37 AM, Trevor Perrin <trevp at trevp.net> wrote:

> So for completeness, I wonder if we should extend NoiseSocket so the
> responder also has a "Reverse" option?
> I'm not sure whether we'd view this as just a role reversal followed by IN,
> or a "modified" IN, such as:

I'll try to summarize this issue, and make a proposal:

A Noise protocol is a fixed, "linear" sequence of messages and crypto
ops.  There are no runtime decisions, except aborting on errors.  This
keeps things simple.

However, some situations might require "branching" (negotiating
protocol versions or crypto choices; 0-RTT fallback).

So far we've viewed that as switching from one "linear" Noise protocol
to another (e.g. switching from IK to XXfallback, if the server can't
decrypt the 0-RTT IK message).

I like how this confines runtime decisions to a single point:  What
Noise protocol are you executing?  You might switch from one protocol
to another, but aside from that, everything else has the simplicity of
a "linear" protocol.

There's a terminology question:

If a "Noise protocol" is a linear protocol (like
"Noise_XX_25519_SHA512_AESGCM"), then what is a "Noise Pipe" (where a
server supports XX, as well as IK with XXfallback)?  I'll tentatively
call it a "compound protocol".

There's also a notation issue:

In a "compound protocol", it's not clear how to handle the roles of
"initiator" and "responder".  For example, if the client initiates a
connection to the server and sends an IK message that the server can't
decrypt, the server will be "initiating" the XXfallback.  But since
initiator-sent messages are notated with right-pointing arrows,
reading IK and XXfallback back-to-back would be confusing if we didn't
do something to prevent the client<->server message direction from

Our current spec treats fallback patterns as a special case where the
responder sends the first message, allowing us to describe the
IK/XXfallback sequence without flipping the message direction:

IK(s, rs):
    <- s
    -> e, es, s, ss
    <- e, ee, se

XXfallback(e, s, rs):
    -> e
    <- e, ee, s, es
    -> s, se

However there are non-fallback cases were the server might initiate a
new Noise protocol.  My previous message described a client attempting
NX_25519, and the server responding by initiating IN_448.

Given this, special-casing "fallback" seems like a limited solution we
should replace with something more general.

We could name the parties "Alice" and "Bob", and have right-pointing
arrows represent messages from Alice to Bob (and vice versa):

 Alice -> Bob
 Alice <- Bob

In a simple Noise protocol, Alice is the initiator (initiator =
whoever sends the first message).
In a compound protocol, Alice is the initiator in the first Noise protocol.

Handshake patterns could be written in either Alice-initiated form
(the default), or Bob-initiated.  Converting from one to the other
requires reversing arrow directions, and changing "se" <-> "es".

For example, here is the N pattern as Alice-initiated, then as Bob-initiated:

    <- s
    -> e, es

    -> s
    <- e, se

Now we can write Alice-initiated NX and Bob-initiated IN, and it's
easier to read what happens if Bob rejects Alice's initial NX message
and initiates IN in response:

    -> e
    <- e, ee, s, es

    <- e, s
    -> e, ee, se

Fallback patterns would cease to be a special notation.  The
"fallback" modifier would move public keys sent in the initiator's
first message into the responder's pre-message, and then re-interpret
the pattern as Bob-initiated:

XXfallback(s, rs, re):
    -> e
    <- e, ee, s, es
    -> s, se

This is the same as XXfallback above except that the pre-message
ephemeral is now interpreted as belonging to the responder, not the
initiator (before we kept the I/R roles fixed but allowed R to send
the first message; now we're keeping the A/B roles fixed, but defining
I/R in terms of who sends the first message).  This is still just a
notation difference which doesn't affect calculations.

This also means that for NoiseSocket we don't have to treat "fallback"
and "reverse" as separate choices by the server.  Instead, they're
both examples of the server simply "switching" from one pattern to
another.  So the server's options, as expressed through the server's
NoiseSocket response message, would be:

EXPLICIT REJECT (uses negotiation_data; empty noise_message)
SWITCH (uses negotiation_data and noise_message)
ACCEPT (empty negotiation data; uses noise_message)



More information about the Noise mailing list