Table of Contents

1. Introduction

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.

2. Overview

2.1. Terminology

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.

2.2. Overview of handshake state machine

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

Each party maintains the following variables:

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. The possible tokens are:

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.

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

The following sections flesh out the details, and add some complications. However, the core of Noise is this simple system of variables, tokens, and processing rules, which allow concise expression of a range of protocols.

3. Message format

All Noise messages are less than or equal to 65535 bytes in length. Restricting message size has several advantages:

All Noise messages can be processed without parsing, since there are no type or length fields. Of course, Noise messages might be encapsulated within a higher-level protocol that contains type and length information. Noise messages might encapsulate payloads that require parsing of some sort, but payloads are handled by the application, not by Noise.

A Noise transport message is simply an AEAD ciphertext that is less than or equal to 65535 bytes in length, and that consists of an encrypted payload plus 16 bytes of authentication data. The details depend on the AEAD cipher function, e.g. AES256-GCM, or ChaCha20-Poly1305, but typically the authentication data is either a 16-byte authentication tag appended to the ciphertext, or a 16-byte synthetic IV prepended to the ciphertext.

A Noise handshake message is also less than or equal to 65535 bytes. It begins with a sequence of one or more DH public keys, as determined by its message pattern. Following the public keys will be a single payload which can be used to convey certificates or other handshake data, but can also contain a zero-length plaintext.

Static public keys and payloads will be in cleartext if they are sent in a handshake prior to a DH operation, and will be AEAD ciphertexts if they occur after a DH operation. (If Noise is being used with pre-shared symmetric keys, this rule is different; see Section 9). Like transport messages, AEAD ciphertexts will expand each encrypted field (whether static public key or payload) by 16 bytes.

For an example, consider the handshake pattern:

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

The first message consists of a cleartext public key ("e") followed by a cleartext payload (remember that a payload is implicit at the end of each message pattern). The second message consists of a cleartext public key ("e") followed by an encrypted public key ("s") followed by an encrypted payload. The third message consists of an encrypted public key ("s") followed by an encrypted payload.

Assuming each payload contains a zero-length plaintext, and DH public keys are 56 bytes, the message sizes will be:

  1. 56 bytes (one cleartext public key and a cleartext payload)
  2. 144 bytes (two public keys, the second encrypted, and encrypted payload)
  3. 88 bytes (one encrypted public key and encrypted payload)

 

4. Crypto functions

A Noise protocol is instantiated with a concrete set of DH functions, cipher functions, and hash functions. The signature for these functions is defined below. Some concrete functions are defined in Section 12.

The following notation will be used in algorithm pseudocode:

4.1. DH functions

Noise depends on the following DH functions (and an associated constant):

4.2. Cipher functions

Noise depends on the following cipher functions:

4.3. Hash functions

Noise depends on the following hash function (and associated constants):

Noise defines additional functions based on the above HASH() function:

Note that temp_key, output1, output2, and output3 are all HASHLEN bytes in length. Also note that the HKDF() function is simply HKDF from [4] with the chaining_key as HKDF salt, and zero-length HKDF info.

5. Processing rules

To precisely define the processing rules we adopt an object-oriented terminology, and present three "objects" which encapsulate state variables and contain functions which implement processing logic. These three objects are presented as a hierarchy: each higher-layer object includes one instance of the object beneath it. From lowest-layer to highest, the objects are:

To execute a Noise protocol you Initialize() a HandshakeState. During initialization you specify the handshake pattern, any local key pairs, and any public keys for the remote party you have knowledge of. After Initialize() you call WriteMessage() and ReadMessage() on the HandshakeState to process each handshake message. If any error is signaled by the DECRYPT() or DH() functions then the handshake has failed and the HandshakeState is deleted.

Processing the final handshake message returns two CipherState objects, the first for encrypting transport messages from initiator to responder, and the second for messages in the other direction. At that point the HandshakeState should be deleted except for the hash value h, which may be used for post-handshake channel binding (see Section 11.2).

Transport messages are then encrypted and decrypted by calling EncryptWithAd() and DecryptWithAd() on the relevant CipherState with zero-length associated data. If DecryptWithAd() signals an error due to DECRYPT() failure, then the input message is discarded. The application may choose to delete the CipherState and terminate the session on such an error, or may continue to attempt communications. If EncryptWithAd() or DecryptWithAd() signal an error due to nonce exhaustion, then the application must delete the CipherState and terminate the session.

The below sections describe these objects in detail.

5.1. The CipherState object

A CipherState can encrypt and decrypt data based on its k and n variables:

A CipherState responds to the following functions. The ++ post-increment operator applied to n means "use the current n value, then increment it". The maximum n value (264-1) is reserved for other use. If incrementing n results in 264-1, then any further EncryptWithAd() or DecryptWithAd() calls will signal an error to the caller.

5.2. The SymmetricState object

A SymmetricState object contains a CipherState plus the following variables:

A SymmetricState responds to the following functions:

5.3. The HandshakeState object

A HandshakeState object contains a SymmetricState plus the following variables, any of which may be empty. Empty is a special value which indicates the variable has not yet been initialized.

A HandshakeState also has variables to track its role, and the remaining portion of the handshake pattern:

A HandshakeState responds to the following functions:

6. Prologue

Noise protocols have a prologue input which allows arbitrary data to be hashed into the h variable. If both parties do not provide identical prologue data, the handshake will fail due to a decryption error. This is useful when the parties engaged in negotiation prior to the handshake and want to ensure they share identical views of that negotiation.

For example, suppose Bob communicates to Alice a list of Noise protocols that he is willing to support. Alice will then choose and execute a single protocol. To ensure that a "man-in-the-middle" did not edit Bob's list to remove options, Alice and Bob could include the list as prologue data.

Note that while the parties confirm their prologues are identical, they don't mix prologue data into encryption keys. If an input contains secret data that’s intended to strengthen the encryption, a PSK handshake should be used instead (see Section 9).

7. Handshake patterns

7.1. Handshake pattern basics

A message pattern is some sequence of tokens from the set ("e", "s", "ee", "es", "se", "ss", "psk"). The handling of these tokens within WriteMessage() and ReadMessage() has been described previously, except for the "psk" token, which will be described in Section 9. Future specifications might introduce other tokens.

A pre-message pattern is one of the following sequences of tokens:

A handshake pattern consists of:

The pre-messages represent an exchange of public keys that was somehow performed prior to the handshake, so these public keys must be inputs to Initialize() for the "recipient" of the pre-message.

The first actual handshake message is sent from the initiator to the responder. The next message is sent from the responder, the next from the initiator, and so on in alternating fashion.

The following handshake pattern describes an unauthenticated DH handshake consisting of two message patterns:

NN:
  -> e
  <- e, ee

In the following handshake pattern both the initiator and responder possess static key pairs, and the handshake pattern comprises three message patterns:

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

The handshake pattern names are NN and XX. This naming convention will be explained in Section 7.5.

Non-empty pre-messages are shown as pre-message patterns prior to the delimiter "...". If both parties have a pre-message, the initiator's is listed first, and hashed first. During Initialize(), MixHash() is called on any pre-message public keys, as described in Section 5.3.

The following handshake pattern describes a handshake where the initiator has pre-knowledge of the responder's static public key and uses it for "zero-RTT" encryption:

NK:
  <- s
  ...
  -> e, es 
  <- e, ee

In the following handshake pattern both parties have pre-knowledge of the other's static public key. The initiator's pre-message is listed first:

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

7.2. Alice and Bob

In all handshake patterns shown previously, the initiator is the party on the left (sending with right-pointing arrows) and the responder is the party on the right.

However, multiple Noise protocols might be used within a compound protocol where the responder in one Noise protocol becomes the initiator for a later Noise protocol. As a convenience for terminology and notation in this case, we introduce the notion of Alice and Bob roles which are different from initiator and responder roles. Alice will be viewed as the party on the left (sending messages with right arrows), and Bob will be the party on the right.

Handshake patterns written in canonical form (i.e. Alice-initiated form) assume the initiator is Alice (the left-most party). All processing rules and discussion so far have assumed canonical-form handshake patterns.

However, handshake patterns can be written in Bob-initiated form by reversing the arrows and the DH tokens (e.g. replacing "es" with "se", and vice versa). This doesn't change the handshake pattern, it simply makes it easier to view Alice-initiated and Bob-initiated handshakes side-by-side.

Below are the handshake patterns from the previous section in Bob-initiated form:

NN:
  <- e
  -> e, ee

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

NK:
  -> s
  ...
  <- e, se
  -> e, ee

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

For an example of Bob-initiated notation, see Section 10.2.

7.3. Handshake pattern validity

Handshake patterns must be valid in the following senses:

  1. Parties can only perform DH between private keys and public keys they possess.

  2. Parties must not send their static public key or ephemeral public key more than once per handshake (i.e. including the pre-messages, there must be no more than one occurrence of "e", and one occurrence of "s", in the messages sent by any party).

  3. Parties must not perform a DH calculation more than once per handshake (i.e. there must be no more than one occurrence of "ee", "es", "se", or "ss" per handshake).

  4. After performing a DH between a remote public key (either static or ephemeral) and the local static key, the local party must not call ENCRYPT() unless it has also performed a DH between its local ephemeral key and the remote public key. In particular, this means that (using canonical notation):

    After an "se" token, the initiator must not send a handshake payload or transport payload unless there has also been an "ee" token.

    After an "ss" token, the initiator must not send a handshake payload or transport payload unless there has also been an "es" token.

    After an "es" token, the responder must not send a handshake payload or transport payload unless there has also been an "ee" token.

    After an "ss" token, the responder must not send a handshake payload or transport payload unless there has also been an "se" token.

Patterns failing the first check are obviously nonsense.

The second and third checks outlaw redundant transmission of values, and redundant computation, to simplify implementation and testing.

The fourth check accomplishes two purposes:

Users are recommended to only use the handshake patterns listed below, or other patterns that have been vetted by experts to satisfy the above checks.

7.4. One-way handshake 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.

Following a one-way handshake the sender can send a stream of transport messages, encrypting them using the first CipherState returned by Split(). The second CipherState from Split() is discarded - the recipient must not send any messages using it (as this would violate the rules in Section 7.3).

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

N:
  <- s
  ...
  -> e, es
K:
  -> s
  <- s
  ...
  -> e, es, ss
X:
  <- s
  ...
  -> e, es, s, ss

N is a conventional DH-based public-key encryption. The other patterns add sender authentication, where the sender's public key is either known to the recipient beforehand (K) or transmitted under encryption (X).

7.5. Interactive handshake patterns (fundamental)

The following handshake patterns represent interactive protocols. These 12 patterns are called the fundamental interactive handshake patterns.

The fundamental interactive patterns are named with two characters, which indicate the status of the initiator and responder's static keys:

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

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

NN:
  -> e
  <- e, ee
   KN:
     -> s
     ...
     -> e
     <- e, ee, se
NK:
  <- s
  ...
  -> e, es
  <- e, ee
   KK:
     -> s
     <- s
     ...
     -> e, es, ss
     <- e, ee, se
NX:
  -> e
  <- e, ee, s, es
    KX:
      -> s
      ...
      -> e
      <- e, ee, se, s, es
XN:
  -> e
  <- e, ee
  -> s, se
    IN:
      -> e, s
      <- e, ee, se
XK:
  <- s
  ...
  -> e, es
  <- e, ee
  -> s, se
    IK:
      <- s
      ...
      -> e, es, s, ss
      <- e, ee, se
XX:
  -> e
  <- e, ee, s, es
  -> s, se
    IX:
      -> e, s
      <- e, ee, se, s, es

The XX pattern is the most generically useful, since it supports mutual authentication and transmission of static public keys.

All fundamental patterns allow some encryption of handshake payloads:

The security properties for handshake payloads are usually weaker than the final security properties achieved by transport payloads, so these early encryptions must be used with caution.

In some patterns the security properties of transport payloads can also vary. In particular: patterns starting with K or I have the caveat that the responder is only guaranteed "weak" forward secrecy for the transport messages it sends until it receives a transport message from the initiator. After receiving a transport message from the initiator, the responder becomes assured of "strong" forward secrecy.

More analysis of these payload security properties is in Section 7.7.

7.6. Interactive handshake patterns (deferred)

The fundamental handshake patterns in the previous section perform DH operations for authentication ("es" and "se") as early as possible.

An additional set of handshake patterns can be described which defer these authentication DHs to the next message. To name these deferred handshake patterns, the numeral "1" is used after the first and/or second character in a fundamental pattern name to indicate that the initiator and/or responder's authentication DH is deferred to the next message.

Deferred patterns might be useful for several reasons:

Below are two examples showing a fundamental handshake pattern on the left, and deferred variant(s) on the right. The full set of 23 deferred handshake patterns are in the Appendix.

NK:
  <- s
  ...
  -> e, es
  <- e, ee
    NK1:
      <- s
      ...
      -> e
      <- e, ee, es
XX:
  -> e
  <- e, ee, s, es
  -> s, se
    X1X:
      -> e
      <- e, ee, s, es
      -> s
      <- se

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

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

7.7. Payload security properties

The following table lists the security properties for Noise handshake and transport payloads for all the one-way patterns in Section 7.4 and the fundamental patterns in Section 7.5. Each payload is assigned a "source" property regarding the degree of authentication of the sender provided to the recipient, and a "destination" property regarding the degree of confidentiality provided to the sender.

The source properties are:

  1. No authentication. This payload may have been sent by any party, including an active attacker.

  2. Sender authentication vulnerable to key-compromise impersonation (KCI). The sender authentication is based on a static-static DH ("ss") involving both parties' static key pairs. If the recipient's long-term private key has been compromised, this authentication can be forged. Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.

  3. Sender authentication resistant to key-compromise impersonation (KCI). The sender authentication is based on an ephemeral-static DH ("es" or "se") between the sender's static key pair and the recipient's ephemeral key pair. Assuming the corresponding private keys are secure, this authentication cannot be forged.

The destination properties are:

  1. No confidentiality. This payload is sent in cleartext.

  2. Encryption to an ephemeral recipient. This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee"). However, the sender has not authenticated the recipient, so this payload might be sent to any party, including an active attacker.

  3. Encryption to a known recipient, forward secrecy for sender compromise only, vulnerable to replay. This payload is encrypted based only on DHs involving the recipient's static key pair. If the recipient's static private key is compromised, even at a later date, this payload can be decrypted. This message can also be replayed, since there's no ephemeral contribution from the recipient.

  4. Encryption to a known recipient, weak forward secrecy. This payload is encrypted based on an ephemeral-ephemeral DH and also an ephemeral-static DH involving the recipient's static key pair. However, the binding between the recipient's alleged ephemeral public key and the recipient's static public key hasn't been verified by the sender, so the recipient's alleged ephemeral public key may have been forged by an active attacker. In this case, the attacker could later compromise the recipient's static private key to decrypt the payload. Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.

  5. Encryption to a known recipient, weak forward secrecy if the sender's private key has been compromised. This payload is encrypted based on an ephemeral-ephemeral DH, and also based on an ephemeral-static DH involving the recipient's static key pair. However, the binding between the recipient's alleged ephemeral public and the recipient's static public key has only been verified based on DHs involving both those public keys and the sender's static private key. Thus, if the sender's static private key was previously compromised, the recipient's alleged ephemeral public key may have been forged by an active attacker. In this case, the attacker could later compromise the intended recipient's static private key to decrypt the payload (this is a variant of a "KCI" attack enabling a "weak forward secrecy" attack). Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.

  6. Encryption to a known recipient, strong forward secrecy. This payload is encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static DH with the recipient's static key pair. Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated by an attacker that has stolen its static private key, this payload cannot be decrypted.

For one-way handshakes, the below-listed security properties apply to the handshake payload as well as transport payloads.

For interactive handshakes, security properties are listed for each handshake payload. Transport payloads are listed as arrows without a pattern. Transport payloads are only listed if they have different security properties than the previous handshake payload sent from the same party. If two transport payloads are listed, the security properties for the second only apply if the first was received.

                         Source         Destination
N                           0                2
K                           1                2
X                           1                2
NN
  -> e                      0                0
  <- e, ee                  0                1
  ->                        0                1
NK
  <- s
  ...
  -> e, es                  0                2
  <- e, ee                  2                1
  ->                        0                5
NX
  -> e                      0                0
  <- e, ee, s, es           2                1
  ->                        0                5
XN
  -> e                      0                0
  <- e, ee                  0                1
  -> s, se                  2                1
  <-                        0                5
XK
  <- s
  ...
  -> e, es                  0                2
  <- e, ee                  2                1
  -> s, se                  2                5
  <-                        2                5
XX
  -> e                      0                0
  <- e, ee, s, es           2                1
  -> s, se                  2                5
  <-                        2                5
KN
  -> s
  ...
  -> e                      0                0
  <- e, ee, se              0                3
  ->                        2                1
  <-                        0                5
KK
  -> s
  <- s
  ...
  -> e, es, ss              1                2
  <- e, ee, se              2                4
  ->                        2                5
  <-                        2                5
KX
  -> s
  ...
  -> e                      0                0
  <- e, ee, se, s, es       2                3
  ->                        2                5
  <-                        2                5
IN
  -> e, s                   0                0
  <- e, ee, se              0                3
  ->                        2                1
  <-                        0                5
IK
  <- s
  ...
  -> e, es, s, ss           1                2
  <- e, ee, se              2                4
  ->                        2                5
  <-                        2                5
IX
  -> e, s                   0                0
  <- e, ee, se, s, es       2                3
  ->                        2                5
  <-                        2                5

7.8. Identity hiding

The following table lists the identity-hiding properties for all the one-way handshake patterns in Section 7.4 and the fundamental handshake patterns in Section 7.5. In addition, we list a few deferred handshake patterns which have different identity-hiding properties than the corresponding fundamental pattern.

Each pattern is assigned properties describing the confidentiality supplied to the initiator's static public key, and to the responder's static public key. The underlying assumptions are that ephemeral private keys are secure, and that parties abort the handshake if they receive a static public key from the other party which they don't trust.

This section only considers identity leakage through static public key fields in handshakes. Of course, the identities of Noise participants might be exposed through other means, including payload fields, traffic analysis, or metadata such as IP addresses.

The properties for the relevant public key are:

  1. Transmitted in clear.

  2. Encrypted with forward secrecy, but can be probed by an anonymous initiator.

  3. Encrypted with forward secrecy, but sent to an anonymous responder.

  4. Not transmitted, but a passive attacker can check candidates for the responder's private key and determine whether the candidate is correct. An attacker could also replay a previously-recorded message to a new responder and determine whether the two responders are the "same" (i.e. are using the same static key pair) by whether the recipient accepts the message.

  5. Encrypted to responder's static public key, without forward secrecy. If an attacker learns the responder's private key they can decrypt the initiator's public key.

  6. Not transmitted, but a passive attacker can check candidates for the pair of (responder's private key, initiator's public key) and learn whether the candidate pair is correct.

  7. Encrypted but with weak forward secrecy. An active attacker who pretends to be the initiator without the initiator's static private key, then later learns the initiator private key, can then decrypt the responder's public key.

  8. Not transmitted, but an active attacker who pretends to be the initator without the initiator's static private key, then later learns a candidate for the initiator private key, can then check whether the candidate is correct.

  9. Encrypted with forward secrecy to an authenticated party.

  10. An active attacker who pretends to be the initiator and records a single protocol run can then check candidates for the responder's public key.

           Initiator      Responder
N              -              3
K              5              5
X              4              3
NN             -              -
NK             -              3
NK1            -              9
NX             -              1
XN             2              -
XK             8              3
XK1            8              9
XX             8              1
KN             7              -
KK             5              5
KX             7              6
IN             0              -
IK             4              3
IK1            0              9
IX             0              6

8. Protocol names and modifiers

To produce a Noise protocol name for Initialize() 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:

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 "/".

Additional rules apply to each name section, as specified below.

8.1. Handshake pattern name section

A handshake pattern name section contains a handshake pattern name plus a sequence of zero or more pattern modifiers.

The handshake pattern name must be an uppercase ASCII string containing only alphabetic characters or numerals (e.g. "XX1" or "IK").

Pattern modifiers specify arbitrary extensions or modifications to the behavior specified by the handshake pattern. For example, a modifier could be applied to a handshake pattern which transforms it into a different pattern according to some rule. The "psk0" and "fallback" modifiers are examples of this, and will be defined later in this document.

A pattern modifier is named with a lowercase alphanumeric ASCII string which must begin with an alphabetic character (not a numeral). The pattern modifier is appended to the base pattern as described below:

The first modifier added onto a base pattern is simply appended. Thus the "fallback" modifier, when added to the "XX" pattern, produces "XXfallback". Additional modifiers are separated with a plus sign. Thus, adding the "psk0" modifier would result in the name section "XXfallback+psk0", or a full protocol name such as "Noise_XXfallback+psk0_25519_AESGCM_SHA256".

In some cases the sequential ordering of modifiers will specify different protocols. However, if the order of some modifiers does not matter, then they are required to be sorted alphabetically (this is an arbitrary convention to ensure interoperability).

8.2. Cryptographic algorithm name sections

The rules for the DH, cipher, and hash name sections are identical. Each name section must contain one or more algorithm names separated by plus signs.

Each algorithm name must consist solely of alphanumeric characters and the forward-slash character ("/"). Algorithm names are recommended to be short, and to use the "/" character only when necessary to avoid ambiguity (e.g. "SHA3/256" is preferable to "SHA3256").

In most cases there will be a single algorithm name in each name section (i.e. no plus signs). Multiple algorithm names are only used when called for by the pattern or a modifier.

None of the patterns or modifiers in this document require multiple algorithm names in any name section. However, this functionality might be useful in future extensions. For example, multiple algorithm names might be used in the DH section to specify "hybrid" post-quantum forward secrecy; or multiple hash algorithms might be specified for different purposes.

9. Pre-shared symmetric keys

Noise provides a pre-shared symmetric key or PSK mode to support protocols where both parties have a 32-byte shared secret key.

9.1. Cryptographic functions

PSK mode uses the SymmetricState.MixKeyAndHash() function to mix the PSK into both the encryption keys and the h value.

Note that MixKeyAndHash() uses HKDF(..., 3). The third output from HKDF() is used as the k value so that calculation of k may be skipped if k is not used.

9.2. Handshake tokens

In a PSK handshake, a "psk" token is allowed to appear one or more times in a handshake pattern. This token can only appear in message patterns (not pre-message patterns). This token is processed by calling MixKeyAndHash(psk), where psk is a 32-byte secret value provided by the application.

In non-PSK handshakes, the "e" token in a pre-message pattern or message pattern always results in a call to MixHash(e.public_key). In a PSK handshake, all of these calls are followed by MixKey(e.public_key). In conjunction with the validity rule in the next section, this ensures that PSK-based encryption uses encryption keys that are randomized using ephemeral public keys as nonces.

9.3. Validity rule

To prevent catastrophic key reuse, handshake patterns using the "psk" token must follow an additional validity rule:

This rule guarantees that a k derived from a PSK will never be used for encryption unless it has also been randomized by MixKey(e.public_key) using a self-chosen ephemeral public key.

9.4. Pattern modifiers

To indicate PSK mode and the placement of the "psk" token, pattern modifiers are used (see Section 8). The modifier psk0 places a "psk" token at the beginning of the first handshake message. The modifiers psk1, psk2, etc., place a "psk" token at the end of the first, second, etc., handshake message.

Any pattern using one of these modifiers must process tokens according to the rules in Section 9.2, and must follow the validity rule in Section 9.3.

The table below lists some unmodified one-way patterns on the left, and the recommended PSK pattern on the right:

N:
  <- s
  ...
  -> e, es
   Npsk0:
     <- s
     ...
     -> psk, e, es
K:
  -> s
  <- s
  ...
  -> e, es, ss
   Kpsk0:
     -> s
     <- s
     ...
     -> psk, e, es, ss
X:
  <- s
  ...
  -> e, es, s, ss
   Xpsk1:
     <- s
     ...
     -> e, es, s, ss, psk

Note that the psk1 modifier is recommended for X. This is because X transmits the initiator's static public key. Because PSKs are typically pairwise, the responder likely cannot determine the PSK until it has decrypted the initiator's static public key. Thus, psk1 is likely to be more useful here than psk0.

Following similar logic, we can define the most likely interactive PSK patterns:

NN:
  -> e
  <- e, ee
NNpsk0:
  -> psk, e
  <- e, ee
NN:
  -> e
  <- e, ee
NNpsk2:
  -> e
  <- e, ee, psk
NK:
  <- s
  ...
  -> e, es
  <- e, ee
NKpsk0:
  <- s
  ...
  -> psk, e, es
  <- e, ee
NK:
  <- s
  ...
  -> e, es
  <- e, ee
NKpsk2:
  <- s
  ...
  -> e, es
  <- e, ee, psk
NX:
  -> e
  <- e, ee, s, es
 NXpsk2:
   -> e
   <- e, ee, s, es, psk
XN:
  -> e
  <- e, ee
  -> s, se
 XNpsk3:
   -> e
   <- e, ee
   -> s, se, psk
XK:
  <- s
  ...
  -> e, es
  <- e, ee
  -> s, se
 XKpsk3:
   <- s
   ...
   -> e, es
   <- e, ee
   -> s, se, psk
XX:
  -> e
  <- e, ee, s, es
  -> s, se
 XXpsk3:
   -> e
   <- e, ee, s, es
   -> s, se, psk
KN:
  -> s
  ...
  -> e
  <- e, ee, se
  KNpsk0:
    -> s
    ...
    -> psk, e
    <- e, ee, se
KN:
  -> s
  ...
  -> e
  <- e, ee, se
  KNpsk2:
    -> s
    ...
    -> e
    <- e, ee, se, psk
KK:
  -> s
  <- s
  ...
  -> e, es, ss
  <- e, ee, se
  KKpsk0:
    -> s
    <- s
    ...
    -> psk, e, es, ss
    <- e, ee, se
KK:
  -> s
  <- s
  ...
  -> e, es, ss
  <- e, ee, se
  KKpsk2:
    -> s
    <- s
    ...
    -> e, es, ss
    <- e, ee, se, psk
KX:
  -> s
  ...
  -> e
  <- e, ee, se, s, es
   KXpsk2:
     -> s
     ...
     -> e
     <- e, ee, se, s, es, psk
IN:
  -> e, s
  <- e, ee, se
   INpsk1:
     -> e, s, psk
     <- e, ee, se
IN:
  -> e, s
  <- e, ee, se
   INpsk2:
     -> e, s
     <- e, ee, se, psk
IK:
  <- s
  ...
  -> e, es, s, ss
  <- e, ee, se
   IKpsk1:
     <- s
     ...
     -> e, es, s, ss, psk
     <- e, ee, se
IK:
  <- s
  ...
  -> e, es, s, ss
  <- e, ee, se
   IKpsk2:
     <- s
     ...
     -> e, es, s, ss
     <- e, ee, se, psk
IX:
  -> e, s
  <- e, ee, se, s, es
   IXpsk2:
     -> e, s
     <- e, ee, se, s, es, psk

The above list does not exhaust all possible patterns that can be formed with these modifiers. In particular, any of these PSK modifiers can be safely applied to any previously named pattern, resulting in patterns like IKpsk0, KKpsk1, or even XXpsk0+psk3, which aren't listed above.

This still doesn't exhaust all the ways that "psk" tokens could be used outside of these modifiers (e.g. placement of "psk" tokens in the middle of a message pattern). Defining additional PSK modifiers is outside the scope of this document.

10. Compound protocols

10.1. Rationale for compound protocols

So far we've assumed Alice and Bob wish to execute a single Noise protocol chosen by the initiator (Alice). However, there are a number of reasons why Bob might wish to switch to a different Noise protocol after receiving Alice's first message. For example:

Handling these scenarios requires a compound protocol where Bob switches from the initial Noise protocol chosen by Alice to a new Noise protocol. In such a compound protocol the roles of initiator and responder would be reversed - Bob would become the initiator of the new Noise protocol, and Alice the responder.

Compound protocols introduce significant complexity as Alice needs to advertise the Noise protocol she is beginning with and the Noise protocol(s) she is capable of switching to, and both parties have to negotiate a secure transition.

These details are largely out of scope for this document. However, to give an example of how compound protocols can be constructed, and to provide some building blocks, the following sections define a fallback modifier and show how it can be used to create a Noise Pipe compound protocol.

Noise Pipes support the XX pattern, but also allow Alice to cache Bob's static public key and attempt an IK handshake with 0-RTT encryption.

In case Bob can't decrypt Alice's initial IK message, he will switch to the XXfallback pattern, which essentially allows the parties to complete an XX handshake as if Alice had sent an XX initial message instead of an IK initial message.

10.2. The fallback modifier

The fallback modifier converts an Alice-initiated pattern to a Bob-initiated pattern by converting Alice's initial message to a pre-message that Bob must receive through some other means (e.g. via an initial IK message from Alice). After this conversion, the rest of the handshake pattern is interpreted as a Bob-initiated handshake pattern.

For example, here is the fallback modifier applied to XX to produce XXfallback:

 

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

XXfallback:                   
  -> e
  ...
  <- e, ee, s, es
  -> s, se

Note that fallback can only be applied to handshake patterns in Alice-initiated form where Alice's first message is capable of being interpreted as a pre-message (i.e. it must be either "e", "s", or "e, s").

10.3. Zero-RTT and Noise protocols

A typical compound protocol for zero-RTT encryption involves three different Noise protocols:

There must be some way for Bob to distinguish the full versus zero-RTT cases on receiving the first message. If Alice makes a zero-RTT attempt, there must be some way for her to distinguish the zero-RTT versus switch cases on receiving the response.

For example, each handshake message could be preceded by some negotiation data, such as a type byte (see Section 13). This data is not part of the Noise message proper, but signals which Noise protocol is being used.

10.4. Noise Pipes

This section defines the Noise Pipe compound protocol. The following handshake patterns satisfy the full, zero-RTT, and switch roles discussed in the previous section, so can be used to provide a full handshake with a simple zero-RTT option:

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

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

XXfallback:                   
  -> e
  ...
  <- e, ee, s, es
  -> s, se

The XX pattern is used for a full handshake if the parties haven't communicated before, after which Alice can cache Bob's static public key.

The IK pattern is used for a zero-RTT handshake.

The XXfallback pattern is used for a switch handshake if Bob fails to decrypt an initial IK message (perhaps due to having changed his static key).

10.5. Handshake indistinguishability

Parties might wish to hide from an eavesdropper which type of handshake they are performing. For example, suppose parties are using Noise Pipes, and want to hide whether they are performing a full handshake, zero-RTT handshake, or fallback handshake.

This is fairly easy:

This leaves the Noise ephemeral public keys in the clear. Ephemeral public keys are randomly chosen DH public values, but they will typically have enough structure that an eavesdropper might suspect the parties are using Noise, even if the eavesdropper can't distinguish the different handshakes. To make the ephemerals indistinguishable from random byte sequences, techniques like Elligator [5] could be used.

11. Advanced features

11.1. Dummy keys

Consider a protocol where an initiator will authenticate herself if the responder requests it. This could be viewed as the initiator choosing between patterns like NX and XX based on some value inside the responder's first handshake payload.

Noise doesn't directly support this. Instead, this could be simulated by always executing XX. The initiator can simulate the NX case by sending a dummy static public key if authentication is not requested. The value of the dummy public key doesn't matter.

This technique is simple, since it allows use of a single handshake pattern. It also doesn't reveal which option was chosen from message sizes or computation time. It could be extended to allow an XX pattern to support any permutation of authentications (initiator only, responder only, both, or none).

Similarly, dummy PSKs (e.g. a PSK of all zeros) would allow a protocol to optionally support PSKs.

11.2. Channel binding

Parties might wish to execute a Noise protocol, then perform authentication at the application layer using signatures, passwords, or something else.

To support this, Noise libraries may call GetHandshakeHash() after the handshake is complete and expose the returned value to the application as a handshake hash which uniquely identifies the Noise session.

Parties can then sign the handshake hash, or hash it along with their password, to get an authentication token which has a "channel binding" property: the token can't be used by the receiving party with a different sesssion.

11.3. Rekey

Parties might wish to periodically update their cipherstate keys using a one-way function, so that a compromise of cipherstate keys will not decrypt older messages. Periodic rekey might also be used to reduce the volume of data encrypted under a single cipher key (this is usually not important with good ciphers, though note the discussion on AESGCM data volumes in Section 14).

To enable this, Noise supports a Rekey() function which may be called on a CipherState.

It is up to to the application if and when to perform rekey. For example:

Applications must make these decisions on their own; there are no pattern modifiers which specify rekey behavior.

Note that rekey only updates the cipherstate's k value, it doesn't reset the cipherstate's n value, so applications performing rekey must still perform a new handshake if sending 264 or more transport messages.

11.4. Out-of-order transport messages

In some use cases, Noise transport messages might be lost or arrive out-of-order (e.g. when messages are sent over UDP). To handle this, an application protocol can send the n value used for encrypting each transport message alongside that message. On receiving such a message the recipient would call the SetNonce() function on the receiving CipherState using the received n value.

Recipients doing this must track the received n values for which decryption was successful and reject any message which repeats such a value, to prevent replay attacks.

Note that lossy and out-of-order message delivery introduces many other concerns (including out-of-order handshake messages and denial of service risks) which are outside the scope of this document.

11.5. Half-duplex protocols

In some application protocols the parties strictly alternate sending messages. In this case Noise can be used in a half-duplex mode [6] where the first CipherState returned by Split() is used for encrypting messages in both directions, and the second CipherState returned by Split() is unused. This allows some small optimizations, since Split() only has to calculate a single output CipherState, and both parties only need to store a single CipherState during the transport phase.

This feature must be used with extreme caution. In particular, it would be a catastrophic security failure if the protocol is not strictly alternating and both parties encrypt different messages using the same CipherState and nonce value.

12. DH functions, cipher functions, and hash functions

12.1. The 25519 DH functions

12.2. The 448 DH functions

12.3. The ChaChaPoly cipher functions

12.4. The AESGCM cipher functions

12.5. The SHA256 hash function

12.6. The SHA512 hash function

12.7. The BLAKE2s hash function

12.8. The BLAKE2b hash function

13. Application responsibilities

An application built on Noise must consider several issues:

14. Security considerations

This section collects various security considerations:

15. Rationales

This section collects various design rationales.

15.1. Ciphers and encryption

Cipher keys and PSKs are 256 bits because:

Nonces are 64 bits because:

The authentication data in a ciphertext (i.e. the authentication tag or synthetic IV) is 128 bits because:

Ciphertexts are required to be indistinguishable from random because:

Rekey defaults to using encryption with the nonce 264-1 because:

Rekey doesn't reset n to zero because:

The AESGCM data volume limit is 256 bytes because:

Cipher nonces are big-endian for AESGCM, and little-endian for ChaCha20, because:

15.2. Hash functions and hashing

The recommended hash function families are SHA2 and BLAKE2 because:

Hash output lengths of both 256 bits and 512 bits are supported because:

The MixKey() design uses HKDF because:

HMAC is used with all hash functions instead of allowing hashes to use a more specialized function (e.g. keyed BLAKE2), because:

MixHash() is used instead of sending all inputs directly through MixKey() because:

The h value hashes handshake ciphertext instead of plaintext because:

15.3. Other

Big-endian length fields are recommended because:

Session termination is left to the application because:

Explicit random nonces (like TLS "Random" fields) are not used because:

16. IPR

The Noise specification (this document) is hereby placed in the public domain.

17. Acknowledgements

Noise is inspired by:

General feedback on the spec and design came from: Moxie Marlinspike, Jason Donenfeld, Rhys Weatherley, Mike Hamburg, David Wong, Jake McGinty, Tiffany Bennett, Jonathan Rudenberg, Stephen Touset, Tony Arcieri, Alex Wied, Alexey Ermishkin, Olaoluwa Osuntokun, Karthik Bhargavan, and Nadim Kobeissi.

Helpful editorial feedback came from: Tom Ritter, Karthik Bhargavan, David Wong, Klaus Hartke, Dan Burkert, Jake McGinty, Yin Guanhao, Nazar Mokrynskyi, Keziah Elis Biermann, Justin Cormack, Katriel Cohn-Gordon, and Nadim Kobeissi.

Helpful input and feedback on the key derivation design came from: Moxie Marlinspike, Hugo Krawczyk, Samuel Neves, Christian Winnerlein, J.P. Aumasson, and Jason Donenfeld.

The PSK approach was largely motivated and designed by Jason Donenfeld, based on his experience with PSKs in WireGuard.

The deferred patterns resulted from discussions with Justin Cormack. The pattern derivation rules in the Appendix are also from Justin Cormack.

The security properties table for deferred patterns was derived by the Noise Explorer tool, from Nadim Kobeissi.

The rekey design benefited from discussions with Rhys Weatherley, Alexey Ermishkin, and Olaoluwa Osuntokun.

The BLAKE2 team (in particular J.P. Aumasson, Samuel Neves, and Zooko) provided helpful discussion on using BLAKE2 with Noise.

Jeremy Clark, Thomas Ristenpart, and Joe Bonneau gave feedback on earlier versions.

18. Appendices

18.1. Deferred patterns

The following table lists all 23 deferred handshake patterns in the right column, with their corresponding fundamental handshake pattern in the left column. See Section 7 for an explanation of fundamental and deferred patterns.

NK:
  <- s
  ...
  -> e, es
  <- e, ee
    NK1:
      <- s
      ...
      -> e
      <- e, ee, es
NX:
  -> e
  <- e, ee, s, es
    NX1:
      -> e
      <- e, ee, s
      -> es
XN:
  -> e
  <- e, ee
  -> s, se
    X1N:
      -> e
      <- e, ee
      -> s
      <- se
XK:
  <- s
  ...
  -> e, es
  <- e, ee
  -> s, se
    X1K:
      <- s
      ...
      -> e, es
      <- e, ee
      -> s
      <- se

    XK1:
      <- s
      ...
      -> e
      <- e, ee, es
      -> s, se

    X1K1:
      <- s
      ...
      -> e
      <- e, ee, es
      -> s
      <- se
XX:
  -> e
  <- e, ee, s, es
  -> s, se
    X1X:
      -> e
      <- e, ee, s, es
      -> s
      <- se

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

    X1X1:
      -> e
      <- e, ee, s
      -> es, s
      <- se
KN:
  -> s
  ...
  -> e
  <- e, ee, se
    K1N:
      -> s
      ...
      -> e
      <- e, ee
      -> se
KK:
  -> s
  <- s
  ...
  -> e, es, ss
  <- e, ee, se
    K1K:
      -> s
      <- s
      ...
      -> e, es
      <- e, ee
      -> se

    KK1:
      -> s
      <- s
      ...
      -> e
      <- e, ee, se, es

    K1K1:
      -> s
      <- s
      ...
      -> e
      <- e, ee, es
      -> se
KX:
  -> s
  ...
  -> e
  <- e, ee, se, s, es
    K1X:
      -> s
      ...
      -> e
      <- e, ee, s, es
      -> se

    KX1:
      -> s
      ...
      -> e
      <- e, ee, se, s
      -> es

    K1X1:
      -> s
      ...
      -> e
      <- e, ee, s
      -> se, es
IN:
  -> e, s
  <- e, ee, se
    I1N:
      -> e, s
      <- e, ee
      -> se
IK:
  <- s
  ...
  -> e, es, s, ss
  <- e, ee, se
    I1K:
      <- s
      ...
      -> e, es, s
      <- e, ee
      -> se

    IK1:
      <- s
      ...
      -> e, s
      <- e, ee, se, es

    I1K1:
      <- s
      ...
      -> e, s
      <- e, ee, es
      -> se
IX:
  -> e, s
  <- e, ee, se, s, es
    I1X:
      -> e, s
      <- e, ee, s, es
      -> se

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

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

18.2. Security properties for deferred patterns

The following table lists the the security properties for the Noise handshake and transport payloads for all the deferred patterns in the previous section. The security properties are labelled using the notation from Section 7.7.

                         Source         Destination
NK1
  <- s
  ...
  -> e                      0                0
  <- e, ee, es              2                1
  ->                        0                5
NX1
  -> e                      0                0
  <- e, ee, s               0                1
  -> es                     0                3
  ->                        2                1
  <-                        0                5
X1N
  -> e                      0                0
  <- e, ee                  0                1
  -> s                      0                1
  <- se                     0                3
  ->                        2                1
X1K
  <- s
  ...
  -> e, es                  0                2
  <- e, ee                  2                1
  -> s                      0                5
  <- se                     2                3
  ->                        2                5
  <-                        2                5
XK1
  <- s
  ...
  -> e                      0                0
  <- e, ee, es              2                1
  -> s, se                  2                5
  <-                        2                5
X1K1
  <- s
  ...
  -> e                      0                0
  <- e, ee, es              2                1
  -> s                      0                5
  <- se                     2                3
  ->                        2                5
  <-                        2                5
X1X
  -> e                      0                0
  <- e, ee, s, es           2                1
  -> s                      0                5
  <- se                     2                3
  ->                        2                5
  <-                        2                5
XX1
  -> e                      0                0
  <- e, ee, s               0                1
  -> es, s, se              2                3
  <-                        2                5
  ->                        2                5
X1X1
  -> e                      0                0
  <- e, ee, s               0                1
  -> es, s                  0                3
  <- se                     2                3
  ->                        2                5
  <-                        2                5
K1N
  -> s
  ...
  -> e                      0                0
  <- e, ee                  0                1
  -> se                     2                1
  <-                        0                5
K1K
  -> s
  <- s
  ...
  -> e, es                  0                2
  <- e, ee, se              2                1
  -> se                     2                5
  <-                        2                5
KK1
  -> s
  <- s
  ...
  -> e                      0                0
  <- e, ee, se, es          2                3
  ->                        2                5
  <-                        2                5
K1K1
  -> s
  <- s
  ...
  -> e                      0                0
  <- e, ee, es              2                1
  -> se                     2                5
  <-                        2                5
K1X
  -> s
  ...
  -> e                      0                0
  <- e, ee, s, es           2                1
  -> se                     2                5
  <-                        2                5
KX1
  -> s
  ...
  -> e                      0                0
  <- e, ee, se, s           0                3
  -> es                     2                3
  <-                        2                5
  ->                        2                5
K1X1
  -> s
  ...
  -> e                      0                0
  <- e, ee, s               0                1
  -> se, es                 2                3
  <-                        2                5
  ->                        2                5
I1N
  -> e, s                   0                0
  <- e, ee                  0                1
  -> se                     2                1
  <-                        0                5
I1K
  <- s
  ...
  -> e, es, s               0                2
  <- e, ee                  2                1
  -> se                     2                5
  <-                        2                5
IK1
  <- s
  ...
  -> e, s                   0                0
  <- e, ee, se, es          2                3
  ->                        2                5
  <-                        2                5
I1K1
  <- s
  ...
  -> e, s                   0                0
  <- e, ee, es              2                1
  -> se                     2                5
  <-                        2                5
I1X
  -> e, s                   0                0
  <- e, ee, s, es           2                1
  -> se                     2                5
  <-                        2                5
IX1
  -> e, s                   0                0
  <- e, ee, se, s           0                3
  -> es                     2                3
  <-                        2                5
  ->                        2                5
I1X1
  -> e, s                   0                0
  <- e, ee, s               0                1
  -> se, es                 2                3
  <-                        2                5
  ->                        2                5

18.3. Pattern derivation rules

The following rules were used to derive the one-way, fundamental, and deferred handshake patterns.

First, populate the pre-message contents as defined by the pattern name.

Next populate the initiator's first message by applying the first rule from the below table which matches. Then delete the matching rule and repeat this process until no more rules can be applied. If this is a one-way pattern, it is now complete.

Otherwise, populate the responder's first message in the same way. Once no more responder rules can be applied, then switch to the initiator's next message and repeat this process, switching messages until no more rules can be applied by either party.

Initiator rules:

  1. Send "e".
  2. Perform "ee" if "e" has been sent, and received.
  3. Perform "se" if "s" has been sent, and "e" received. If initiator authentication is deferred, skip this rule for the first message in which it applies, then mark the initiator authentication as non-deferred.
  4. Perform "es" if "e" has been sent, and "s" received. If responder authentication is deferred, skip this rule for the first message in which it applies, then mark the responder authentication as non-deferred.
  5. Perform "ss" if "s" has been sent, and received, and "es" has been performed, and this is the first message, and initiator authentication is not deferred.
  6. Send "s" if this is the first message and initiator is "I" or one-way "X".
  7. Send "s" if this is not the first message and initiator is "X".

Responder rules:

  1. Send "e".
  2. Perform "ee" if "e" has been sent, and received.
  3. Perform "se" if "e" has been sent, and "s" received. If initiator authentication is deferred, skip this rule for the first message in which it applies, then mark the initiator authentication as non-deferred.
  4. Perform "es" if "s" has been sent, and "e" received. If responder authentication is deferred, skip this rule for the first message in which it applies, then mark the responder authentication as non-deferred.
  5. Send "s" if responder is "X".

18.4. Change log

Revision 34:

19. References

[1] P. Rogaway, “Authenticated-encryption with Associated-data,” in Proceedings of the 9th ACM Conference on Computer and Communications Security, 2002. http://web.cs.ucdavis.edu/~rogaway/papers/ad.pdf

[2] Okamoto, Tatsuaki and Pointcheval, David, “The Gap-Problems: A New Class of Problems for the Security of Cryptographic Schemes,” in Proceedings of the 4th International Workshop on Practice and Theory in Public Key Cryptography: Public Key Cryptography, 2001. https://www.di.ens.fr/~pointche/Documents/Papers/2001_pkc.pdf

[3] H. Krawczyk, M. Bellare, and R. Canetti, “HMAC: Keyed-Hashing for Message Authentication.” Internet Engineering Task Force; RFC 2104 (Informational); IETF, Feb-1997. http://www.ietf.org/rfc/rfc2104.txt

[4] H. Krawczyk and P. Eronen, “HMAC-based Extract-and-Expand Key Derivation Function (HKDF).” Internet Engineering Task Force; RFC 5869 (Informational); IETF, May-2010. http://www.ietf.org/rfc/rfc5869.txt

[5] D. J. Bernstein, M. Hamburg, A. Krasnova, and T. Lange, “Elligator: Elliptic-curve points indistinguishable from uniform random strings.” Cryptology ePrint Archive, Report 2013/325, 2013. http://eprint.iacr.org/2013/325

[6] Markku-Juhani O. Saarinen, “Beyond Modes: Building a Secure Record Protocol from a Cryptographic Sponge Permutation.” Cryptology ePrint Archive, Report 2013/772, 2013. http://eprint.iacr.org/2013/772

[7] A. Langley, M. Hamburg, and S. Turner, “Elliptic Curves for Security.” Internet Engineering Task Force; RFC 7748 (Informational); IETF, Jan-2016. http://www.ietf.org/rfc/rfc7748.txt

[8] Y. Nir and A. Langley, “ChaCha20 and Poly1305 for IETF Protocols.” Internet Engineering Task Force; RFC 7539 (Informational); IETF, May-2015. http://www.ietf.org/rfc/rfc7539.txt

[9] M. J. Dworkin, “SP 800-38D. Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC,” National Institute of Standards & Technology, Gaithersburg, MD, United States, 2007. http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf

[10] NIST, “FIPS 180-4. Secure Hash Standard (SHS),” National Institute of Standards & Technology, Gaithersburg, MD, United States, 2012. http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf

[11] M.-J. Saarinen and J.-P. Aumasson, “The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC).” Internet Engineering Task Force; RFC 7693 (Informational); IETF, Nov-2015. http://www.ietf.org/rfc/rfc7693.txt

[12] H. Krawczyk, “‘Cryptographic extraction and key derivation: The hkdf scheme’.” Cryptology ePrint Archive, Report 2010/264, 2010. http://eprint.iacr.org/2010/264

[13] D. J. Bernstein, T. Lange, and P. Schwabe, “NaCl: Networking and Cryptography Library.”. https://nacl.cr.yp.to/

[14] D. J. Bernstein, “CurveCP: Usable security for the Internet.”. https://curvecp.org

[15] H. Krawczyk, “SIGMA: The ‘SIGn-and-MAc’ Approach to Authenticated Diffie-Hellman and Its Use in the IKE Protocols,” in Advances in Cryptology - CRYPTO 2003, 2003. http://webee.technion.ac.il/~hugo/sigma.html

[16] S. Halevi and H. Krawczyk, “One-Pass HMQV and Asymmetric Key-Wrapping.” Cryptology ePrint Archive, Report 2010/638, 2010. http://eprint.iacr.org/2010/638

[17] I. Goldberg, D. Stebila, and B. Ustaoglu, “Anonymity and One-way Authentication in Key Exchange Protocols,” Design, Codes, and Cryptography, vol. 67, no. 2, May 2013. http://cacr.uwaterloo.ca/techreports/2011/cacr2011-11.pdf

[18] M. Di Raimondo, R. Gennaro, and H. Krawczyk, “Secure Off-the-record Messaging,” in Proceedings of the 2005 ACM Workshop on Privacy in the Electronic Society, 2005. http://www.dmi.unict.it/diraimondo/web/wp-content/uploads/papers/otr.pdf

[19] C. Kudla and K. G. Paterson, “Modular Security Proofs for Key Agreement Protocols,” in Advances in Cryptology - ASIACRYPT 2005: 11th International Conference on the Theory and Application of Cryptology and Information Security, 2005. http://www.isg.rhul.ac.uk/~kp/ModularProofs.pdf

[20] S. Blake-Wilson, D. Johnson, and A. Menezes, “Key agreement protocols and their security analysis,” in Crytography and Coding: 6th IMA International Conference Cirencester, UK, December 17–19, 1997 Proceedings, 1997. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.387

[21] M. Hamburg, “Key Exchange and DuplexWrap-like protocols.” Noise@moderncrypto.org Mailing List, 2015. https://moderncrypto.org/mail-archive/noise/2015/000098.html

[22] Mike Hamburg, “The STROBE protocol framework.” Cryptology ePrint Archive, Report 2017/003, 2017. http://eprint.iacr.org/2017/003

[23] T. Perrin and M. Marlinspike, “The Double Ratchet Algorithm,” 2016. https://whispersystems.org/docs/specifications/doubleratchet/