[noise] Simple 1-RTT protocol

Trevor Perrin trevp at trevp.net
Sun Jun 11 16:23:44 PDT 2017


On Sun, Jun 11, 2017 at 1:04 AM, Trevor Perrin <trevp at trevp.net> wrote:
> We've talked about a "NoiseSocket" protocol that would be the default
> usage for Noise.
[...]
> Here's a simpler proposal:
[...]
>
>  -> ClientHello(client_version: byte, options: bytes[])
>  <- ServerAuth(server_version: byte, server_credentials: bytes[])
>  -> ClientAuth(client_credentials: bytes[])



We could simplify further:  instead of client_version and
server_version, just have a single client version.

If the server supports newer versions the server can communicate this
to the client in the server's response payload.  If the client cares,
it can open a new session with a higher version.

If the server doesn't support the client's version, the server closes
the connection, and the client can try falling back to an older
version.

This doesn't allow the client to offer multiple versions
simultaneously, but I'm not sure that's worth the complexity.

I'm also not sure "NoiseSocket" is a good name.  It sounds like an API
endpoint rather than a protocol, and a simpler name might be better
for such a simple construct.  "NoiseLink", maybe?

Anyways, updated sketch:


Protocol messages
==================

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

With names and arguments:

 -> ClientHello(version: byte, cleartext_payload: bytes[])
 <- ServerAuth(server_auth_payload: bytes[])
 -> ClientAuth(client_auth_payload: bytes[])

The server_auth_payload and client_auth_payload are good for sending
credentials such as certificates.  If the server supports a higher
version, it should indicate this in server_auth_payload, so that the
client can initiate a new session using a higher version.  Encoding
details for this are up to the application.

Parties should ignore any handshake payloads they don't recognize.  If
handshake payloads are populated, it should be with an extensible
format like Protobufs, JSON, or XML, and parties should ignore any
fields they don't recognize.


Message framing
================

ClientHello:
 - 1 byte: version
 - 2 bytes: length of following message
 - <message>

Other messages:
 - 2 bytes: length of following message
 - <message>


Prologue
=========
Since we can't know how applications will use the version field, we
should probably bind it:

"NoiseLink" || version


API
====

    descriptor = pair of (version, (DH, Cipher, Hash))
    descriptorList = list of descriptors

InitializeClientSession(descriptor)
InitializeServerSession(descriptorList)

WriteClientHello(cleartext_payload=empty) -> handshake_message
ReadClientHello(handshake_message) -> (version, cleartext_payload)

WriteServerAuth(server_key_pair=empty, server_auth_payload=empty) ->
handshake_message
ReadServerAuth(handshake_message) -> (server_pub_key, server_auth_payload)

WriteClientAuth(client_key_pair=empty, client_auth_payload=empty) ->
handshake_message
ReadClientAuth(handshake_message) -> (client_pub_key, client_auth_payload)

Write(payload) -> transport_message
Read(transport_message) -> payload


Trevor


More information about the Noise mailing list