Draft:Noise Protocol Framework
The Noise Protocol Framework, sometimes known as Noise or Noise Framework, allows for the design of secure channel protocols between two parties, having specific cryptographic properties as compared to a protocol like TLS. Noise is the basis of some protocols with significant deployment such as Slack’s Nebula, WhatsApp and WireGuard.
A secure channel protocol has 2 phases:
- the handshake phase: authenticates and establishes shared secret keys using Diffie-Hellman key exchange (DH) for Authenticated Key Exchange (AKE)
- the transport phase: uses shared secret keys to encrypt data
The Noise Framework is described in the public-domain Specification and allows for the development of concrete Noise Protocols such as Noise_IK_448_ChaChaPoly_BLAKE2b
where the name consists of a handshake pattern IK
, followed by names of the DH, cipher and hash functions. TLS1.3 cipher suites such as TLS_CHACHA20_POLY1305_SHA256
are
analagous except for a handshake pattern.
The handshake pattern can be described in a diagram as a set of messages, each annotated with a list of tokens that describe cryptographic operations performed on a party's handshake state.
Example handshake pattern having 3 messages:
IK
<- s
...
-> e, es, s, ss
<- e, ee, se
Handshake names are formulaic:
I
= Static key for initiator Immediately transmitted to responder, despite reduced or absent identity hidingK
= Static key for initiator Known to responder
The line(s) before ...
represent a message prior to DH AKE such as an out-of-band tranfer of a public key.
The Specification lists 3 one-way handshake patterns, and 12 fundamental interactive handshake patterns. There are variations of some of these:
- deferred patterns, where the authentication DHs are deferred to the next message. A numeral
1
is used after the first and/or second character, e.g.NK1
orX1X1
- a pre-shared symmetric key or PSK mode to support protocols where both parties have a 32-byte shared secret key, e.g.
Npsk0
orXpsk1
- compound protocols in which the roles of initiator and responder get reversed as a negotiation mechanism via the
fallback
modifier. A Noise Pipe is an example found in §10.4
Each handshake pattern can be combined with one of the 16 combination of the 8 cryptographic algorithms listed in the Specification. As those algorithms are of comparable quality and do not enlarge the design space.
The Specification outlines an API in §5 using the following objects each having a small set of methods:
- A
CipherState
object contains k and n variables, which it uses to encrypt and decrypt ciphertexts. During the handshake phase each party has a singleCipherState
, but during the transport phase each party has twoCipherState
objects: one for sending, and one for receiving. - A
SymmetricState
object contains aCipherState
plus ck and h variables. It is so-named because it encapsulates all the "symmetric crypto" used by Noise. During the handshake phase each party has a singleSymmetricState
, which can be deleted once the handshake is finished. - A
HandshakeState
object contains aSymmetricState
plus DH variables (s, e, rs, re) and a variable representing the handshake pattern. During the handshake phase each party has a singleHandshakeState
, which can be deleted once the handshake is finished.
The implementation of a concrete protocol involves the design of message representation, as well as aspects outside the Noise Framework. An example of the latter happens with protocols using UDP transports, such as WireGuard which uses a sliding window to handle out-of-order arrival.
Security properties of several handshake patterns are described in the Specification and can support mutual authentication, forward secrecy, zero round-trip encryption, identity hiding and other advanced features . Formal cryptographic analyses of common handshake patterns have appeared in the academic literature[1][2]. The second effort has resulted in the online tool Noise Explorer
Much of the following consists of excerpts from the Specification with formatting:
IK
for protocol names comprised of handshake patterns, cryptography & modifiers- ck for variables in the handshake state machine
- e for tokens in a message pattern
- § prefixes references to sections in the Specification
with the focus on:
- handshake patterns
- security properties and tradeoffs
- application responsibilities & security considerations
Background
[edit]The framework was developed by Trevor Perrin with support from Moxie Marlinspike based on work done at Open Whisper Systems.
Why "Noise"
[edit]"Noise" refers to one of the design rationales:
Ciphertexts are required to be indistinguishable from random because:
This makes Noise protocols easier to use with random padding (for length-hiding), or for censorship-resistant "unfingerprintable" protocols, or with Steganography. However note that ephemeral keys are likely to be distinguishable from random unless a technique such as Elligator is used.
Possibly also a pun on Signal (software).
DH Based Protocols (from RWC 2018 talk)
[edit]Most secure channel protocols use an AKE based on signatures (for authentication) and Diffie-Hellman (for key exchange). In last 10-15 years, growing interest in DH-based AKEs (without signatures).
Elegant, but each protocol starts from scratch
- Idea #1: Combine simple elements to make different protocols
- Idea #2: Use “sponge-like” symmetric crypto (idea from Mike Hamburg’sStrobe)
Development
[edit]The initial commit for the Specification was on Aug 4, 2014 and underwent many changes following discussion on the mailing list until rev34 on Jul 11, 2018. NB originally maintained in Wiki starting from 10-Feb-2013.
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:
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 "/".
Additional rules apply to each name section, as specified below.
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).
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.
The Specification lists 8 modern algorithms with the following names.
Diffie-Hellman Functions | |
---|---|
25519 |
Curve25519 |
448 |
Curve448 |
Cipher Functions | |
ChaChaPoly |
ChaCha20-Poly1305 |
AESGCM |
Advanced Encryption Standard (AES) in Galois/Counter Mode (GCM) |
Hash Functions | |
SHA256 |
SHA256 |
SHA512 |
SHA512 |
BLAKE2s |
BLAKE2s |
BLAKE2b |
BLAKE2b |
The Wiki has this list of unofficial algorithms; I've omitted the Post-Quantum ones as the entries pre-date the NIST Post-Quantum Cryptography Standardization effort starting in 2016 with the first three Post Quantum Crypto Standards: FIPS 203, FIP 204, and FIP 205 in 2024.
Here we document some names which could be used for nonstandard algorithms, so that experimental use of these algorithms could use consistent names (NOTE: None of these algorithms are endorsed for use with Noise, use at your own risk).
Diffie-Hellman Functions | |
---|---|
secp256k1 |
secp256k1, used by Lightning |
FourQ |
FourQ |
NIST P256 |
P-256 |
NIST P384 |
P-384 |
NIST P521 |
P-521 |
Cipher Functions | |
DeoxysII |
used by Nyquist |
AESGCMSIV |
AES-GCM-SIV |
AESPMACSIV |
AES-GCM-SIV |
Kravatte |
Kravatte |
KravatteSIV |
Kravatte-SIV |
Hash Functions | |
SHA3/256 |
SHA-3#Instances |
SHA3/512 |
SHA-3#Instances |
SHAKE128 |
SHA-3#Instances (HASHLEN=32) |
SHAKE256 |
SHA-3#Instances (HASHLEN=64) |
K12 |
Kangaroo12 |
M14 |
Marsupilami14 |
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 §9).
Handshake Patterns
[edit]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 §7.3).
One-way patterns are named with a single character, which indicates the status of the sender's static key:
N
= No static key for senderK
= Static key for initiator Known to responderX
= Static key for sender Xmitted ("transmitted") to recipient
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
).
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:
N
=N
o static key for initiatorK
= Static key for initiatorK
nown to responderX
= Static key for initiatorX
mitted ("transmitted") to responderI
= Static key for initiatorI
mmediately transmitted to responder, despite reduced or absent identity hiding
The second character refers to the responder's static key:
N
=N
o static key for responderK
= Static key for responderK
nown to initiatorX
= Static key for responderX
mitted ("transmitted") to initiator
NN | ||
---|---|---|
0 | 0 | #1 -> e |
0 | 1 | #2 <- e, ee |
0 | 1 | #3 -> |
NK | ||
#1 <- s | ||
... | ||
0 | 2 | #2 -> e, es |
2 | 1 | #3 <- e, ee |
0 | 5 | #4 -> |
NX | ||
0 | 0 | #1 -> e |
2 | 1 | #2 <- e, ee, s, es |
0 | 5 | #3 -> |
XN | ||
0 | 0 | #1 -> e |
0 | 1 | #2 <- e, ee |
2 | 1 | #3 -> s, se |
0 | 5 | #4 <- |
XK | ||
#1 <- s | ||
... | ||
0 | 2 | #2 -> e, es |
2 | 1 | #3 <- e, ee |
2 | 5 | #4 -> s, se |
2 | 5 | #5 <- |
XX | ||
0 | 0 | #1 -> e |
2 | 1 | #2 <- e, ee, s, es |
2 | 5 | #3 -> s, se |
2 | 5 | #4 <- |
KN | ||
#1 -> s | ||
... | ||
0 | 0 | #2 -> e |
0 | 3 | #3 <- e, ee, se |
2 | 1 | #4 -> |
0 | 5 | #5 <- |
KK | ||
#1 -> s | ||
#2 <- s | ||
... | ||
1 | 2 | #3 -> e, es, ss |
2 | 4 | #4 <- e, ee, se |
2 | 5 | #5 -> |
2 | 5 | #6 <- |
KX | ||
#1 -> s | ||
... | ||
0 | 0 | #2 -> e |
2 | 3 | #3 <- e, ee, se, s, es |
2 | 5 | #4 -> |
2 | 5 | #5 <- |
IN | ||
0 | 0 | #1 -> e, s |
0 | 3 | #2 <- e, ee, se |
2 | 1 | #3 -> |
0 | 5 | #4 <- |
IK | ||
#1 <- s | ||
... | ||
1 | 2 | #2 -> e, es, s, ss |
2 | 4 | #3 <- e, ee, se |
2 | 5 | #4 -> |
2 | 5 | #5 <- |
IX | ||
0 | 0 | #1 -> e, s |
2 | 3 | #2 <- e, ee, se, s, es |
2 | 5 | #3 -> |
2 | 5 | #4 <- |
The first two columns in in the table above, prior to each message pattern, lists the security properties for Noise handshake and transport payloads for all the one-way patterns in §7.4 and the fundamental patterns in §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.
For the sender:
- 0. No authentication. This payload may have been sent by any party, including an active attacker.
Used by: IN
#1, IN
#2, IN
#4, IX
#1, KN
#2, KN
#3, KN
#5, KX
#2, NK
#2, NK
#4, NN
#1, NN
#2, NN
#3, NX
#1, NX
#3, XK
#2, XN
#1, XN
#2, XN
#4, XX
#1
- 1. 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.
Used by: IK
#2, IN
#3, KK
#3, KN
#4, NK
#3, NN
#2, NN
#3, NX
#2, XK
#3, XN
#2, XN
#3, XX
#2
- 2. 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.
Used by: IK
#2, IK
#3, IK
#4, IK
#5, IN
#3, IX
#2, IX
#3, IX
#4, KK
#3, KK
#4, KK
#5, KK
#6, KN
#4, KX
#3, KX
#4, KX
#5, NK
#2, NK
#3, NX
#2, XK
#2, XK
#3, XK
#4, XK
#5, XN
#3, XX
#2, XX
#3, XX
#4
For the recipient:
- 0. No confidentiality. This payload is sent in cleartext.
Used by: IN
#1, IN
#2, IN
#4, IX
#1, KN
#2, KN
#3, KN
#5, KX
#2, NK
#2, NK
#4, NN
#1, NN
#2, NN
#3, NX
#1, NX
#3, XK
#2, XN
#1, XN
#2, XN
#4, XX
#1
- 1. 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.
Used by: IK
#2, IN
#3, KK
#3, KN
#4, NK
#3, NN
#2, NN
#3, NX
#2, XK
#3, XN
#2, XN
#3, XX
#2
- 2. 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.
Used by: IK
#2, IK
#3, IK
#4, IK
#5, IN
#3, IX
#2, IX
#3, IX
#4, KK
#3, KK
#4, KK
#5, KK
#6, KN
#4, KX
#3, KX
#4, KX
#5, NK
#2, NK
#3, NX
#2, XK
#2, XK
#3, XK
#4, XK
#5, XN
#3, XX
#2, XX
#3, XX
#4
- 3. 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.
Used by: IN
#2, IX
#2, KN
#3, KX
#3
- 4. 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.
Used by: IK
#3, KK
#4
- 5. 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.
Used by: IK
#4, IK
#5, IN
#4, IX
#3, IX
#4, KK
#5, KK
#6, KN
#5, KX
#4, KX
#5, NK
#4, NX
#3, XK
#4, XK
#5, XN
#4, XX
#3, XX
#4
The following table lists the identity-hiding properties for all the one-way handshake patterns in §7.4 and the fundamental handshake patterns in §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.
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 |
The properties for the relevant public key are:
- 0. Transmitted in clear.
- 1. Encrypted with forward secrecy, but can be probed by an anonymous initiator.
- 2. Encrypted with forward secrecy, but sent to an anonymous responder.
- 3. 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.
- 4. 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.
- 5. 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.
- 6. 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.
- 7. 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.
- 8. Encrypted with forward secrecy to an authenticated party.
- 9. 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.
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:
- The initiator might have prior knowledge of the responder's static public key, but not wish to send any 0-RTT encrypted data.
- In some cases, deferring authentication can improve the identity-hiding properties of the handshake (see §7.8).
- Future extensions to Noise might be capable of replacing DH operations with signatures or KEM ciphertexts, but would only be able to do so if the sender is authenticating themselves (signatures) or the sender is authenticating the recipient (KEM ciphertexts). Thus every fundamental handshake pattern is only capable of having each authentication DH replaced with a signature or KEM ciphertext, but the deferred variants make both replacements possible.
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 §18.
NK | NK1 |
---|---|
<- s | <- s |
... | ... |
-> e, es | -> e |
-> e, ee | -> e, ee, es |
XX | X1X |
-> e | -> e |
<- e, ee, s, es | <- e, ee, s, es |
-> s, se | -> s |
<- se | |
XX1 | |
-> e | |
<- e, ee, s | |
-> es, s, se | |
X1X1 | |
-> e | |
<- e, ee, s | |
-> es, s | |
<- se |
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:
Alice might have chosen a Noise Protocol based on a cipher, DH function, or handshake pattern which Bob doesn't support.
Alice might have sent a "zero-RTT" encrypted initial message based on an out-of-date version of Bob's static public key or PSK.
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.
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").
A typical compound protocol for zero-RTT encryption involves three different Noise Protocols:
- A full protocol is used if Alice doesn't possess stored information about Bob that would enable zero-RTT encryption, or doesn't wish to use the zero-RTT handshake.
- A zero-RTT protocol allows encryption of data in the initial message.
- A switch protocol is triggered by Bob if he can't decrypt Alice's first zero-RTT handshake message.
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 §13). This data is not part of the Noise message proper, but signals which Noise Protocol is being used.
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).
NoiseLingo negotiation language on top of NoiseSocket
[edit]Email from Trevor Perrin on 4-Mar-2018
I've created a draft spec for an "NLS" framework that adds a negotiation language ("NoiseLingo") on top of NoiseSocket (hence "NoiseLingoSocket"). This is based on ideas from 1.
This needs a tweaked NoiseSocket draft, with modifications from 2 (renaming a couple things, and changing the prologue calculation to differentiate the "retry" case, and to add an application prologue):
The NLS draft also defines some "basic profiles", which are intended as high-level protocols usable by application developers:
- NoiseLink (1-RTT handshake)
- NoiseZeroLink (0-RTT handshake)
- NoiseShortLink (for low-end embedded)
- NoiseAnonBox (public-key encryption)
- NoseAuthBox (public-key encryption + sender auth)
The idea is that NoiseLingo and NLS give you a menu of negotiation fields that are easy to choose from to create profiles. Also, these profiles will have a lot of similarity and thus potential for interop (e.g. a NoiseZeroLink client can talk to a NoiseLink server, by falling back to 1-RTT). And if you start with something simple like NoiseLink, it's easy to add new NLS fields and negotiation options as you discover new needs.
An application built on Noise must consider several issues:
- Choosing crypto functions: The
25519
DH functions are recommended for typical uses, though the448
DH functions might offer extra security in case a cryptanalytic attack is developed against elliptic curve cryptography. The448
DH functions should be used with a 512-bit hash likeSHA512
orBLAKE2b
. The25519
DH functions may be used with a 256-bit hash likeSHA256
orBLAKE2s
, though a 512-bit hash might offer extra security in case a cryptanalytic attack is developed against the smaller hash functions.AESGCM
is hard to implement with high speed and constant time in software. - Extensibility: Applications are recommended to use an extensible data format for the payloads of all messages (e.g. JSON, Protocol Buffers). This ensures that fields can be added in the future which are ignored by older implementations.
- Padding Applications are recommended to use a data format for the payloads of all encrypted messages that allows padding. This allows implementations to avoid leaking information about message sizes. Using an extensible data format, per the previous bullet, may be sufficient.
- Session termination: Applications must consider that a sequence of Noise transport messages could be truncated by an attacker. Applications should include explicit length fields or termination signals inside of transport payloads to signal the end of an interactive session, or the end of a one-way stream of transport messages.
- Length fields: Applications must handle any framing or additional length fields for Noise messages, considering that a Noise message may be up to 65535 bytes in length. If an explicit length field is needed, applications are recommended to add a 16-bit big-endian length field prior to each message.
- Negotiation data: Applications might wish to support the transmission of some negotiation data prior to the handshake, and/or prior to each handshake message. Negotiation data could contain things like version information and identifiers for Noise Protocols. For example, a simple approach would be to send a single-byte type field prior to each Noise handshake message. More flexible approaches might send extensible structures such as protobufs. Negotiation data introduces significant complexity and security risks such as rollback attacks (see next section).
This section collects various security considerations:
- Authentication: A Noise Protocol with static public keys verifies that the corresponding private keys are possessed by the participant(s), but it's up to the application to determine whether the remote party's static public key is acceptable. Methods for doing so include certificates which sign the public key (and which may be passed in handshake payloads), preconfigured lists of public keys, or "pinning" / "key-continuity" approaches where parties remember public keys they encounter and check whether the same party presents the same public key in the future.
- Session termination: Preventing attackers from truncating a stream of transport
- Rollback: If parties decide on a Noise Protocol based on some previous negotiation that is not included as prologue, then a rollback attack might be possible. This is a particular risk with compound protocols, and requires careful attention if a Noise handshake is preceded by communication between the parties.
- Static key reuse: A static key pair used with Noise should be used with a single hash algorithm. The key pair should not be used outside of Noise, nor with multiple hash algorithms. It is acceptable to use the static key pair with different Noise Protocols, provided the same hash algorithm is used in all of them. (Reusing a Noise static key pair outside of Noise would require extremely careful analysis to ensure the uses don't compromise each other, and security proofs are preserved).
- PSK reuse: A PSK used with Noise should be used with a single hash algorithm. The PSK should not be used outside of Noise, nor with multiple hash algorithms.
- Ephemeral key reuse: Every party in a Noise Protocol must send a fresh ephemeral public key prior to sending any encrypted data. Ephemeral keys must never be reused. Violating these rules is likely to cause catastrophic key reuse. This is one rationale behind the patterns in §7, and the validity rules in §7.3. It's also the reason why one-way handshakes only allow transport messages from the sender, not the recipient.
- Misusing public keys as secrets: It might be tempting to use a pattern with a pre-message public key and assume that a successful handshake implies the other party's knowledge of the public key. Unfortunately, this is not the case, since setting public keys to invalid values might cause predictable DH output. For example, a
Noise_NK_25519
initiator might send an invalid ephemeral public key to cause a known DH output of all zeros, despite not knowing the responder's static public key. If the parties want to authenticate with a shared secret, it should be used as a PSK. - Channel binding: Depending on the DH functions, it might be possible for a malicious party to engage in multiple sessions that derive the same shared secret key by setting public keys to invalid values that cause predictable DH output (as in the previous bullet). It might also be possible to set public keys to equivalent values that cause the same DH output for different inputs. This is why a higher-level protocol should use the handshake hash (h) for a unique channel binding, instead of ck, as explained in §11.2.
- Incrementing nonces: Reusing a nonce value for n with the same key k for encryption would be catastrophic. Implementations must carefully follow the rules for nonces. Nonces are not allowed to wrap back to zero due to integer overflow, and the maximum nonce value is reserved. This means parties are not allowed to send more than 2⁶⁴-1 transport messages.
- Protocol names: The protocol name used with
Initialize()
must uniquely identify the combination of handshake pattern and crypto functions for every key it's used with (whether ephemeral key pair, static key pair, or PSK). If the same secret key was reused with the same protocol name but a different set of cryptographic operations then bad interactions could occur. - Pre-shared symmetric keys: Pre-shared symmetric keys must be secret values with 256 bits of entropy.
- Data volumes: The
AESGCM
cipher functions suffer a gradual reduction in security as the volume of data encrypted under a single key increases. Due to this, parties should not send more than 2⁵⁶ bytes (roughly 72 petabytes) encrypted by a single key. If sending such large volumes of data is a possibility then different cipher functions should be chosen. - Hash collisions: If an attacker can find hash collisions on prologue data or the handshake hash, they may be able to perform "transcript collision" attacks that trick the parties into having different views of handshake data. It is important to use Noise with collision-resistant hash functions, and replace the hash function at any sign of weakness.
- Implementation fingerprinting: If this protocol is used in settings with anonymous parties, care should be taken that implementations behave identically in all cases. This may require mandating exact behavior for handling of invalid DH public keys.
Implementations
[edit]Language | Name |
---|---|
C | Noise-C |
C# | Noise.NET |
CLI | noisecat |
Erlang | noise |
Java | Noise-Java |
JavaScript/WASM | noise-c.wasm (from Noise-C) |
Haskell | cacophony |
Go | noise |
Go | nyquist |
Go | NoisePlugAndPlay |
Objective-C | Noise.framework (macOS and iOS compatible framework, Swift friendly) |
Python | noiseprotocol |
Python | Dissononce |
Racket | noise-protocol |
Ruby | Noise |
Rust | Snow |
Rust | Noise-Rust |
Concrete Protocols
[edit]- I2P (ntcp2 router)
- Lightning
- libp2p
- Facebook’s Libra / Diem (digital currency) (shutdown in 2022)
- nQUIC
- Slack’s Nebula, "A scalable overlay networking tool "
- WireGuard
Comparison to TLS1.3
[edit]The first draft of RFC 8446 was in Aug-2014
culminating in the release of the Proposed Standard in Aug-2018 after 28 drafts. There was
a short thread on the mailing-list with a comparison to the OPTLS
proposal.
External links
[edit]- was a stub entry until I noticed entry for Noise Protocol Framework in German Wikipedia
- Official website with Specification and Wiki
- Github repos
- slides from a 2017 talk "The Noise Protocol Framework"
- An Introduction to the Noise Protocol Framework
- Using the Noise Protocol Framework to design a distributed capability system
noisecat
: the noise swiss army knife
Presentations:
See Also
[edit]Some other uses of noise in the general cryptographic sense
References
[edit]- ^ Dowling, Benjamin; Rösler, Paul; Schwenk, Jörg (2020), "Flexible Authenticated and Confidential Channel Establishment (fACCE): Analyzing the Noise Protocol Framework", Lecture Notes in Computer Science, Cham: Springer International Publishing, pp. 341–373, doi:10.1007/978-3-030-45374-9_12, hdl:20.500.11850/399156, ISBN 978-3-030-45373-2, retrieved 2024-05-17
- ^ Kobeissi, Nadim; Nicolas, Georgio; Bhargavan, Karthikeyan (June 2019). "Noise Explorer: Fully Automated Modeling and Verification for Arbitrary Noise Protocols". 2019 IEEE European Symposium on Security and Privacy (EuroS&P). IEEE. pp. 356–370. doi:10.1109/eurosp.2019.00034. ISBN 978-1-7281-1148-3.