Noise Protocol Framework

From CryptoWiki
Jump to: navigation, search

Noise is a framework for crypto protocols based on Diffie-Hellman key agreement. Noise can describe protocols that consist of a single message as well as interactive protocols.

Contents

Noise Framework Description

A Noise protocol begins with two parties exchanging handshake messages. During this handshake phase the parties exchange DH public keys and perform a sequence of DH operations, hashing the DH results into a shared secret key. After the handshake phase each party can use this shared key to send encrypted transport messages. The Noise framework supports handshakes where each party has a long-term static key pair and/or an ephemeral key pair. A Noise handshake is described by a simple language. This language consists of tokens which are arranged into message patterns. Message patterns are arranged into handshake patterns. A message pattern is a sequence of tokens that specifies the DH public keys that comprise a handshake message, and the DH operations that are performed when sending or receiving that message. A handshake pattern specifies the sequential exchange of messages that comprise a handshake. A handshake pattern can be instantiated by DH functions, cipher functions, and hash functions to give a concrete Noise protocol.

A handshake message consists of some DH public keys followed by a payload. The payload may contain certificates or other data chosen by the application. To send a handshake message, the sender specifies the payload and sequentially processes each token from a message pattern.

Noise Variables

The core of Noise is a set of variables maintained by each party during a hand-shake, and rules for sending and receiving handshake messages by sequentially processing the tokens from a message pattern.

Each party maintains the following variables:

  • s, e : The local party’s static and ephemeral key pairs (which may be empty).
  • rs, re : The remote party’s static and ephemeral public keys (which may be empty).
  • h : A handshake hash value that hashes all the handshake data that’s been sent and received.
  • ck : A chaining key that hashes all previous DH outputs. Once the handshake completes, the chaining key will be used to derive the encryption keys for transport messages.
  • k, n : An encryption key k (which may be empty) and a counter-based nonce n . Whenever a new DH output causes a new ck to be calculated, a new k is also calculated. The key k and nonce n are used to encrypt static public keys and handshake payloads. Encryption with k uses some AEAD cipher mode and uses the current h value as associated data which is covered by the AEAD authentication. Encryption of static public keys and payloads provides some confidentiality and key confirmation during the handshake phase.

The possible tokens are:

  • "e" : The sender generates a new ephemeral key pair and stores it in the e variable, writes the ephemeral public key as cleartext into the message buffer, and hashes the public key along with the old h to derive a new h .
  • "s" : The sender writes its static public key from the s variable into the message buffer, encrypting it if k is non-empty, and hashes the output along with the old h to derive a new h .
  • "ee", "se", "es", "ss" : A DH is performed between the initiator’s key pair (whether static or ephemeral is determined by the first letter) and the responder’s key pair (whether static or ephemeral is determined by the second letter). The result is hashed along with the old ck to derive a new ck and k , and n is set to zero. After processing the final token in a handshake message, the sender then writes the payload into the message buffer, encrypting it if k is non-empty, and hashes the output along with the old h to derive a new h . As a simple example, an unauthenticated DH handshake is described by the handshake pattern: -> e <- e, ee The initiator sends the first message, which is simply an ephemeral public key. The responder sends back its own ephemeral public key. Then a DH is performed and the output is hashed into a shared secret key. Note that a cleartext payload is sent in the first message, after the cleartext ephemeral public key, and an encrypted payload is sent in the response message, after the cleartext ephemeral public key. The application may send whatever payloads it wants.

After processing the final token in a handshake message, the sender then writes the payload into the message buffer, encrypting it if k is non-empty, and hashes the output along with the old h to derive a new h.

Handshake patterns

A message pattern is some sequence of tokens from the set ("e", "s", "ee", "es", "se", "ss", "psk"). Future specifications might introduce other tokens. A pre-message pattern is one of the following sequences of tokens:

  • "e"
  • "s"
  • "e, s"
  • empty

A handshake pattern consists of:

  • A pre-message pattern for the initiator, representing information about the initiator’s public keys that is known to the responder.
  • A pre-message pattern for the responder, representing information about the responder’s public keys that is known to the initiator.
  • A sequence of message patterns for the actual handshake messages.

The pre-messages represent an exchange of public keys that was somehow performed prior to the handshake

Handshake pattern examples

As a simple example, an unauthenticated DH handshake is described by the handshake pattern:

-> e
<- e, ee

The initiator sends the first message, which is simply an ephemeral public key. The responder sends back its own ephemeral public key. Then a DH is performed and the output is hashed into a shared secret key. Note that a cleartext payload is sent in the first message, after the cleartext ephemeral public key, and an encrypted payload is sent in the response message, after the cleartext ephemeral public key. The application may send whatever payloads it wants.

The responder can send its static public key (under encryption) and authenticate itself via a slightly different pattern:

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

In this case, the final ck and k values are a hash of both DH results. Since the es token indicates a DH between the initiator’s ephemeral key and the responder’s static key, successful decryption by the initiator of the second message’s payload serves to authenticate the responder to the initiator. Note that the second message’s payload may contain a zero-length plaintext, but the payload ciphertext will still contain authentication data (such as an authentication tag or “synthetic IV”), since encryption is with an AEAD mode. The second message’s payload can also be used to deliver certificates for the responder’s static public key. The initiator can send its static public key (under encryption), and authenticate itself, using a handshake pattern with one additional message:

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

Handshake pattern names

The following handshake pattern describes an unauthenticated DH handshake:


NN():
-> e
<- e, ee

The handshake pattern name is NN. The empty parentheses indicate that neither party is initialized with any key pairs. The tokens "s" , "e" , or "e, s" inside the parentheses would indicate that the initiator is initialized with static and/or ephemeral key pairs. The tokens "rs" , "re" , or "re, rs" would indicate the same thing for the responder.

Right-pointing arrows show messages sent by the initiator. Left-pointing arrows show messages sent by the responder.

Non-empty pre-messages are shown as patterns prior to the delimiter "..." , with a right-pointing arrow for the initiator’s pre-message, and a left-pointing arrow for the responder’s pre-message. If both parties have a pre-message, the initiator’s is listed first, and hashed first.

The following pattern describes a handshake where the initiator has pre- knowledge of the responder’s static public key, and performs a DH with the responder’s static public key as well as the responder’s ephemeral public key. This pre-knowledge allows an encrypted payload to be sent in the first message (“zero-RTT encryption”), although full forward secrecy and replay protection is only achieved with the second message.

NK(rs):
<- s
...
-> e, es

One-way patterns

The following handshake patterns represent “one-way” handshakes supporting a one-way stream of data from a sender to a recipient. These patterns could be used to encrypt files, database records, or other non-interactive data streams.

One-way patterns are named with a single character, which indicates the status of the sender’s static key:

  • N = No static key for sender
  • K = Static key for sender Known to recipient
  • X = Static key for sender transmitted to recipients, or other non-interactive data streams.

Examples:

N(rs):
<- s
...
-> e, es

K(s, rs):
-> s
<- s
...
-> e, es, ss

X(s, rs):
<- s
...
-> e, es, s, ss

Interactive patterns

The following handshake patterns represent interactive protocols.

Interactive patterns are named with two characters, which indicate the status of the initator and responder’s static keys:

The first character refers to the initiator’s static key:

  • N = No static key for initiator
  • K = Static key for initiator Known to responder
  • X = Static key for initiator X transmitted to responder
  • I = Static key for initiator Immediately transmitted to responder, despite reduced or absent identity hiding

The second character refers to the responder’s static key:

  • N = No static key for responder
  • K = Static key for responder Known to initiator
  • X = Static key for responder transmitted to initiator

Examples:


NN():
-> e
<- e, ee

KN(s):
-> s
...
-> e
<- e, ee, se

NK(rs):
<- s
...
-> e, es
<- e, ee

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

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

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

XN(s):
-> e
<- e, ee
-> s, se

IN(s):
-> e, s
<- e, ee, se

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

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

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

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

Protocol names

To produce a Noise protocol name you concatenate the ASCII string "Noise_" with four underscore-separated name sections which sequentially name the handshake pattern, the DH functions, the cipher functions, and then the hash functions. The resulting name must be 255 bytes or less.

Examples:

  • Noise_XX_25519_AESGCM_SHA256
  • Noise_N_25519_ChaChaPoly_BLAKE2s
  • Noise_IK_448_ChaChaPoly_BLAKE2b

Each name section must consist only of alphanumeric characters (i.e. characters in one of the ranges "A". . ."Z", "a". . ."z", and "0" . . . "9"), and the two special characters "+" and "/".

Noise usage

Noise is currently used by WhatsApp, WireGuard, Lightning.

Glossary

Protocol

Public key

Private key

Diffie–Hellman key exchange

Cryptographic hash functions

The basics of cryptographic protocol construction and analysis

References

Noise Protocol Framework

Bibliography

Go to Part II. Applications of Cryptography (Cryptographic Protocols)

Main Page