Table of Contents

1. Introduction

The NLS (or NoiseLingoSocket) framework builds on the Noise Protocol Framework and the NoiseSocket encoding layer to provide a rich set of features for building complex protocols. Protocols based on NLS can negotiate their choice of Noise protocol, PSK, and transport phase options, and can also exchange evidence blobs for their static public keys (e.g. certificates).

This document also defines the basic profiles of NLS. Profiles will serve as the basis for implementation and interop in the Noise architecture.

2. Overview

The Noise architecture can be viewed as three layers:

Combinining all these layers gives us an expanded framework such as NLS ("NoiseLingoSocket").

Below we define the NoiseLingo language, the NLS framework based on it, and the notion of profiles based on NLS. Finally, we define a set of basic profiles for NLS (NoiseLink, NoiseZeroLink, NoiseTinyLink, NoiseAnonBox, and NoiseAuthBox).

3. The NoiseLingo negotiation language

3.1. NoiseLingo overview

NoiseLingo defines fields which can be used in negotiation data and handshake payloads. It's unlikely that any protocol will use all of these fields. Instead, profiles of NoiseLingo will use a subset of these fields.

3.2. NoiseLingo definitions

The NoiseLingo message contents are below, described and encoded using the protobuf version 3 ("proto3") language:

The negotiation data for the initial message and its response are below:

message NoiseLingoNegotiationDataRequest {
  string server_name = 1;
  string initial_protocol = 2;
  repeated string switch_protocol = 3;
  repeated string retry_protocol = 4;
  string rejected_protocol = 5;
  bytes psk_id = 6;
}

message NoiseLingoNegotiationDataResponse {
  oneof response {
    string switch_protocol = 3;
    string retry_protocol = 4;
    bool rejected = 5;
  }
}

Each handshake payload can use some subset of the following fields:

message NoiseLingoHandshakePayload {
  repeated string evidence_request_type = 1;
  repeated string evidence_blob_type = 2;
  repeated bytes evidence_blob = 3;
  bytes psk_id = 4;
  NoiseLingoTransportOptions transport_options = 5;
}

message NoiseLingoTransportOptions {
  uint32 max_send_length = 1;
  uint32 max_recv_length = 2;
  bool continuous_rekey = 3;
  bool short_terminated = 4;
}

3.3. NoiseLingo notes

NoiseLingo only uses field numbers in the range 1-6. Field numbers up to 10 in these messages are reserved for future use by NoiseLingo. User-defined extensions should use field numbers 11 and greater.

All NoiseLingo fields have acceptable default values, except initial_protocol. Thus, a zero-length protobuf message is valid in many cases.

3.4. NoiseLingo fields

This section explains the usage of each NoiseLingo field:

3.5. Protocol aliases

Noise protocol names might be long strings, so alias strings are allowed in initial_protocol, switch_protocol, retry_protocol, and rejected_protocol. An alias is any string that is not a Noise protocol name (e.g "1", "2", "aes_protocols", etc.)

An alias may be shorthand for a single protocol name (for initial_protocol, or for switch_protocol and retry_protocol in Response1). An alias might also represent a sequence of protocol names, which are substituted for the alias. If the receiver doesn't recognize an alias they will ignore it, unless that makes the resulting message invalid (e.g. an unrecognized alias in initial_protocol, or in Response1's switch_protocol or retry_protocol).

An alias should begin with either an ASCII lowercase character or digit, to distinguish it from explicitly-named protocols which will start with capital letters (e.g. "Noise_XX_25519_AESGCM_SHA256").

Aliases should be used with caution, as they can prevent interoperability unless both parties have agreed on the same aliases.

4. The NLS framework

NLS combines NoiseLingo with NoiseSocket. The NoiseSocket application prologue is set to "NLS(revision1)". This will change with every revision of this document to emphasize that this is a work-in-progress, and not to be used except for testing.

The NoiseLingoNegotiationData messages are transmitted inside the NoiseSocket negotiation_data fields. If the responder accepts the initiator's initial_protocol, the response negotiation_data is zero-length (according to NoiseSocket).

If the responder requests the initiator to retry a different protocol, the initiator's retry message will reset to the NoiseLingo Request1 message, and so on.

If the responder requests to switch to a different protocol, the NoiseLingo messages will not reset, unless the profile indicates otherwise.

5. Basic profiles

NoiseLink is intended to be the default and "entry-level" use of Noise.

The NoiseLink profile uses the following Noise protocols:

The initiator's initial_protocol will choose one of the first two. Thus, an initiator only needs to implement one of these protocols. For future-proofing, a server must support all of them, and must support the XX protocols for retry_protocol, and the XXfallback protocols for switch_protocol.

message NoiseLinkNegotiationDataRequest1 {
  string server_name = 1;
  string initial_protocol = 2;
  repeated string switch_protocol = 3;
  repeated string retry_protocol = 4;
}

message NoiseLinkHandshakePayloadRequest1 {
  repeated string evidence_request_type = 1;
}

message NoiseLinkNegotiationDataResponse1 {
  oneof response {
    string switch_protocol = 3;
    string retry_protocol = 4;
    bool rejected = 5;
  }
}

message NoiseLinkHandshakePayloadResponse1 {
  repeated string evidence_request_type = 1;
  repeated string evidence_blob_type = 2;
  repeated bytes evidence_blob = 3;
}

message NoiseLinkHandshakePayloadRequest2 {
  repeated string evidence_blob_type = 2;
  repeated bytes evidence_blob = 3;
}

NoiseZeroLink is a superset of NoiseLink which adds a 0-RTT capability. NoiseZeroLink can deliver encrypted and authenticated data in the first handshake payload by using the server's static public key. If the client has an incorrect view of the server's static key, or doesn't know the server's static key, then NoiseZeroLink uses the same 1-RTT XX handshake as NoiseLink.

NoiseZeroLink uses the same messages and Noise protocols as NoiseLink, plus two additional protocols:

The IK protocols can be chosen as an initial protocol, in which case the client offers the corresponding fallback protocol as a switch protocol in case the server has changed its static public key.

NoiseZeroLink implements the Noise Pipes concept from the Noise specification.

NoiseTinyLink is a variant of NoiseLink designed for small messages and constrained devices.

NoiseTinyLink defines aliases "1", "2", and "3" as the following Noise protocols:

The initiator indicates their choice using the alias only. Future versions of this specification may assign values to the aliases "4" through "100".

It is assumed the responder supports whichever aliases the initiator is configured to use. To keep things simple, NoiseTinyLink does not support switch_protocol or retry_protocol. To upgrade to a new protocol, either all responders need to be upgraded before any initiators, or initiators must be upgraded to perform "rejected-retry". Responders are required to send a rejected field when rejecting a client's initial_protocol, to enable rejected-retry.

NoiseTinyLink assumes the parties are configured with a single evidence blob at most, and does not negotiate its type.

Finally, NoiseTinyLink supports max_send_length and max_recv_length to negotiate shorter transport messages.

message NoiseTinyLinkNegotiationDataRequest1 {
  string initial_protocol = 2;
  string rejected_protocol = 5;
}

message NoiseTinyLinkHandshakePayloadRequest1 {
}

message NoiseTinyLinkNegotiationDataResponse1 {
  bool rejected = 5;
}

message NoiseTinyLinkHandshakePayloadResponse1 {
  string evidence_blob_type = 2;
  bytes evidence_blob = 3;
  NoiseTinyLinkTransportOptions transport_options = 4;
}

message NoiseTinyLinkHandshakePayloadRequest2 {
  string evidence_blob_type = 2;
  bytes evidence_blob = 3;
  NoiseTinyLinkTransportOptions transport_options = 4;
}

message NoiseTinyLinkTransportOptions {
  uint32 max_send_length = 1;
  uint32 max_recv_length = 2;
}

5.4. NoiseAnonBox

NoiseAnonBox provides public-key encryption to the recipient's static public key. The following Noise protocols are supported:

Recipients must support both protocols, but senders can choose which to use.

The stream of transport messages is "short-terminated" so the recipient can recognize the final transport message.

message NoiseAnonBoxNegotiationDataRequest1 {
  string initial_protocol = 2;
}

message NoiseAnonBoxHandshakePayloadRequest1 {
  NoiseAnonBoxTransportOptions transport_options = 4;
}

message NoiseAnonBoxTransportOptions {
  uint32 max_send_length = 1;
  bool short_terminated = 4;
}

5.5. NoiseAuthBox

NoiseAuthBox provides authenticated public-key encryption to the recipient's static public key. The following Noise protocols are supported:

Recipients must support both protocols, but senders can choose which to use.

The messages are the same as NoiseBox except the sender can transmit evidence blobs for their public key.

message NoiseAuthBoxNegotiationDataRequest1 {
  string initial_protocol = 2;
}

message NoiseAuthBoxHandshakePayloadRequest1 {
  repeated string evidence_blob_type = 2;
  repeated bytes evidence_blob = 3;
  NoiseAuthBoxTransportOptions transport_options = 4;
}

message NoiseAuthBoxTransportOptions {
  uint32 max_send_length = 1;
  bool short_terminated = 4;
}

6. IPR

This document is hereby placed in the public domain.

7. Acknowledgements

TBD

8. References