This article has multiple issues. Please helpimprove it or discuss these issues on thetalk page.(Learn how and when to remove these messages) (Learn how and when to remove this message)
|
TheNoise Protocol Framework, sometimes referred to as "Noise" or "Noise Framework", is apublic domain cryptographicframework[1] for creatingsecure communicationprotocols based onDiffie–Hellman key exchange.[2] Developed byTrevor Perrin, the framework defines a series ofhandshake patterns—predefined sequences of message exchanges—that outline how parties initiate communication, exchange keys, and establishshared secrets. These patterns can be combined and customized to meet specific security requirements, such asmutual authentication,forward secrecy, and identity protection.
Several popularsoftware applications andprotocols, including the messaging platformsWhatsApp andSlack[3] and the VPN protocolWireGuard, have used implementations of the Noise Framework to ensureend-to-end encryption for user communications. The framework remains a topic of development, includingpost-quantum adaptations.[4] The framework is currently at revision 34, published in July 2018.[1]
Mostsecure channel protocols rely onauthenticated key exchange (AKE) usingdigital signatures (forauthentication) andDiffie–Hellman (forkey exchange). In the 2000s–2010s, interest grew in developing pure Diffie–Hellman-based AKEs, without signatures,[5] leading to both theoretical (e.g., Kudla-Paterson,[6] NAXOS,[7] Ntor)[8] and practical advancements (e.g., Ntor,[8]NaCl,CurveCP,DNSCurve, OPTLS).[9] These were often developed from scratch. The Noise Protocol Framework was developed by Trevor Perrin, with support fromMoxie Marlinspike, introducing two key innovations:[5]
The Framework evolved based on work initially conducted atOpen Whisper Systems, the software organization from which theSignal Protocol andSignal messaging app originated. While unrelated to thesignal processing concept ofnoise, the choice of “Noise” as the name for thiscryptographic protocol might be a play on thesignal vs. noise concept.
Originally maintained as awiki starting from February 10, 2013,[12] the framework's development began with an initialcommit to its specification on August 4, 2014.[13] The framework evolved through numerous revisions following mailing list discussions until version 34 on July 11, 2018.[14] The Noise Protocol Framework acknowledges[15] inspiration from previous cryptographic designs (e.g.,NaCl,CurveCP or theKDF chains used in theDouble Ratchet Algorithm) and contributions from figures in cryptography and computing (e.g.,Jason Donenfeld,Hugo Krawczyk).
During its development, the Noise Protocol Framework evolved alongsideTLS 1.3, including 2015 discussions[16] comparing the protocols, particularly the “OPTLS” proposal.[17] Both projects spanned from 2014 to 2018, with the first draft of TLS 1.3 RFC 8446[18] released in August 2014 and the final Proposed Standard in August 2018. The Noise Framework provided an alternative approach, enabling the selection of specific handshake patterns and cryptographic algorithms to design protocols tailored to specific security properties and performance needs.
Formal verifications[19] of the Noise Protocol Framework have evaluated itssecurity properties. Studies have employed automated tools to model and verify various handshake patterns within the framework,[20][21] assessing theirresilience against a range ofattacks.
A secure channel protocol has two phases:
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 initiatorImmediately transmitted to responder, despite reduced or absent identity hidingK = Static key for initiatorKnown to responder The line(s) before... represent a message prior to DH AKE such as an out-of-band transfer of a public key.
The specification lists three one-way handshake patterns, and 12 fundamental interactive handshake patterns. There are variations of some of these:
1 is used after the first and/or second character, e.g.NK1 orX1X1Npsk0 orXpsk1fallback modifier. A Noise Pipe is an example found in §10.4[22]A real-world example comes from WireGuard whoseConstruction on page 10 of theWhitepaper isNoise_IKpsk2_25519_ChaChaPoly_BLAKE2s.
Each handshake pattern can be combined with one of the 16 combinations of the 8 cryptographic algorithms listed in the Specification. Asthose algorithms are of comparable quality and do not enlarge the design space.
The Specification outlines an API in §5[23] using the followingobjects each having a small set ofmethods:
CipherState object containsk andn 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.SymmetricState object contains aCipherState plusck andh 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.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 usingUDP transports, such asWireGuard, 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.[24][25] The second effort has resulted in the online tool Noise Explorer.[26]
Much of the following consists of excerpts from the Specification with formatting:
IK for protocol names consisting of handshake patterns, cryptography, and modifierswith the focus on:
To produce a Noise Protocol name forInitialize() you concatenate the ASCII stringNoise_ 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.[27] Examples:
Noise_XX_25519_AESGCM_SHA256Noise_N_25519_ChaChaPoly_BLAKE2sNoise_IK_448_ChaChaPoly_BLAKE2bEach 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.[28]
The handshake pattern name must be an uppercase ASCII string containing only alphabetic characters or numerals (e.g.XX1 orIK).
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. Thepsk0 andfallback modifiers are examples of this and will be defined later in this document.
A pattern modifier is named with a lowercase alphanumeric ASCII string that 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, thefallback modifier, when added to theXX pattern, producesXXfallback. Additional modifiers are separated with a plus sign. Thus, adding thepsk0 modifier would result in the name sectionXXfallback+psk0, or a full protocol name such asNoise_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.[29]
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 toSHA3256).
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.[30][31]
| 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;[32] I've omitted the Post-Quantum ones as the entries pre-date theNIST 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[who?] 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,[33] used by Lightning |
FourQ | FourQ[34] |
NIST P256 | P-256[35] |
NIST P384 | P-384[36] |
NIST P521 | P-521[37] |
| Cipher Functions | |
DeoxysII | used by Nyquist |
AESGCMSIV | AES-GCM-SIV |
AESPMACSIV | AES-GCM-SIV |
Kravatte | Kravatte[38] |
KravatteSIV | Kravatte-SIV[39] |
| 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[40] |
M14 | Marsupilami14[41] |
Noise Protocols have a prologue input that 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.[42]
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).
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.[43]
Following a one-way handshake the sender can send a stream of transport messages, encrypting them using the first CipherState returned bySplit() The second CipherState fromSplit() 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 initiatorKnown to responderX = Static key for senderXmitted ("transmitted") to recipientN:
<-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.[44]
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 =No static key for initiatorK = Static key for initiatorKnown to responderX = Static key for initiatorXmitted ("transmitted") to responderI = Static key for initiatorImmediately transmitted to responder, despite reduced or absent identity hidingThe second character refers to the responder's static key:
N =No static key for responderK = Static key for responderKnown to initiatorX = Static key for responderXmitted ("transmitted") to initiatorNN | ||
|---|---|---|
| 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 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:
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
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
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:
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
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
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
Used by:IN#2,IX#2,KN#3,KX#3
Used by:IK#3,KK#4
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.[45]
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:
The fundamental handshake patterns in the previous section perform DH operations for authentication (es andse) as early as possible.[46]
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 numeral1 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 §18.[47]
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:[49]
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 theXX pattern, but also allow Alice to cache Bob's static public key and attempt anIK handshake with 0-RTT encryption.
In case Bob can't decrypt Alice's initialIK message, he will switch to theXXfallback pattern, which essentially allows the parties to complete anXX handshake as if Alice had sent anXX initial message instead of anIK initial message.
fallback modifier §10.2Thefallback 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 initialIK message from Alice). After this conversion, the rest of the handshake pattern is interpreted as a Bob-initiated handshake pattern.[50]
For example, here is thefallback modifier applied toXX to produceXXfallback:
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 eithere,s, or "e,s").
A typical compound protocol for zero-RTT encryption involves three different Noise Protocols:[51]
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:[22]
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
TheXX pattern is used for a full handshake if the parties haven't communicated before, after which Alice can cache Bob's static public key.
TheIK pattern is used for a zero-RTT handshake.
TheXXfallback pattern is used for a switch handshake if Bob fails to decrypt an initialIK message (perhaps due to having changed his static key).
Email from Trevor Perrin on 4-Mar-2018[52]
I've created a draft spec for an "NLS" framework that adds anegotiation language ("NoiseLingo") on top of NoiseSocket (hence"NoiseLingoSocket"). This is based on ideas from 1.[53]
This needs a tweaked NoiseSocket draft, with modifications from 2[54] (renaming a couple things, and changing the prologue calculation todifferentiate the "retry" case, and to add an application prologue):
The NLS draft also defines some "basic profiles", which are intendedas 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 negotiationfields that are easy to choose from to create profiles. Also, theseprofiles will have a lot of similarity and thus potential for interop(e.g. a NoiseZeroLink client can talk to a NoiseLink server, byfalling back to 1-RTT). And if you start with something simple likeNoiseLink, it's easy to add new NLS fields and negotiation options asyou discover new needs.
An application built on Noise must consider several issues:[57]
25519 DH functions are recommended for typical uses, though the448 DH functions might offer extra security in case a cryptanalytic attack is developed againstelliptic 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.This section collects various security considerations:[58]
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.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.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 256 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.| Language | Name |
|---|---|
| C | Noise-C[59] |
| C# | Noise.NET[60] |
| CLI | noisecat[61] |
| Erlang | noise[62] |
| Java | Noise-Java[63] |
| JavaScript/WASM | noise-c.wasm[64] (from Noise-C) |
| Haskell | cacophony[65] |
| Go | noise[66] |
| Go | nyquist[67] |
| Go | NoisePlugAndPlay[68] |
| Objective-C | Noise.framework[69] (macOS and iOS compatible framework, Swift friendly) |
| Python | noiseprotocol[70] |
| Python | Dissononce[71] |
| Racket | noise-protocol[69] |
| Ruby | Noise[72] |
| Rust | Snow[73] |
| Rust | Noise-Rust[74] |
Some other uses of noise in the general cryptographic sense:
{{citation}}: CS1 maint: work parameter with ISBN (link)noisecat: the noise swiss army knifePresentations: