[noise] Simple 1-RTT protocol

Alexey Ermishkin scratch.net at gmail.com
Sat Jun 10 22:40:30 PDT 2017

Hi Trevor, 

I like the idea of describing the API but looks that you've dropped the previously "standardized" way of providing a list of supported ciphersuites. Does that mean we'll need to choose a default one?

-----Original Message-----
From: Noise [mailto:noise-bounces at moderncrypto.org] On Behalf Of Trevor Perrin
Sent: Sunday, June 11, 2017 6:05 AM
To: noise <noise at moderncrypto.org>
Subject: [noise] Simple 1-RTT protocol

We've talked about a "NoiseSocket" protocol that would be the default usage for Noise.  I suggested a complicated versioning scheme which allows clients to offer initial messages from different handshakes, and the server chooses one of them:


Alexey has continued to explore this, and his latest draft is worth reading:


However, I wonder if complicated versioning is the wrong track.  I'd like this to be easy to understand and add to every Noise library, so we might need more simplicity.

Here's a simpler proposal:

Protocol messages

We'd use the Noise_XX pattern:
 -> e
 <- e, ee, s, es
 -> s, es

We'd give these messages names and arguments:

 -> ClientHello(client_version: byte, options: bytes[])
 <- ServerAuth(server_version: byte, server_credentials: bytes[])  -> ClientAuth(client_credentials: bytes[])

The "options" is used as the initial, cleartext payload.  Its usage is up to the application, but it is recommended that applications ignore any contents they don't understand.  This allows applications to later advertise support for new ciphers, or send ephemerals for different curves, or advertise anything else.  However we don't specify how any of that works, and just leave it for the application.

The "version" fields allow the parties to signal compatibility-breaking choices, i.e. if a new client refuses to accept the old client_version=0 cipher, it can signal client_version=1, and old servers will error immediately.  If the client used "options" to offer incompatible choices, servers can use server_version to indicate which they are choosing.

The "server_credentials" and "client_credentials" are used as handshake payloads and are intended to contain certificates, though it's up to the application.  For example, they might be empty if a party is using a "dummy" static public key, and not authenticating.

Message framing

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

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

Since we can't know how all applications will use the version fields, we should probably bind them, so we could do a prologue like:

"NoiseSocket" || client_version || server_version


Because we're trying to make this easy to use, we might be more prescriptive about the API.  I'd suggest:

WriteClientHello(client_version=0, options=empty) -> handshake_message ReadClientHello(version_window=(0,0), handshake_message) -> (client_version, options)

WriteServerAuth(client_version, server_version, server_key_pair=empty,
server_credentials=empty) -> handshake_message ReadServerAuth(version_window=(0,0), handshake_message) -> (server_version, server_pub_key, server_credentials)

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

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

The API reads and writes whole messages, instead of dealing with byte streams, so that the caller can handle buffering and have full control over packetizing.

If the client or server specifies an empty static key pair, the library generates a "dummy" single-use key pair for them.

By requiring clients and servers to specify version windows = (min_version, max_version), we hope that unrecognized versions will cause immediate errors.

Does this have enough extensibility / future-proofing?

I'll argue that "options" lets clients advertise features that are consistent with the original first message, "server_version" lets servers indicate choice of some option, and "client_version" lets clients indicate a break in compatibility in the first message.

Is that enough?

Noise mailing list
Noise at moderncrypto.org

More information about the Noise mailing list