-
Notifications
You must be signed in to change notification settings - Fork 36
Overview
(This is an informal overview; for a full description, see following pages.)
Noise boxes are an authenticated encryption from the sender's ECDH key to the receiver's ECDH key. The sender's public key is transmitted to the intended receiver but is hidden from an eavesdropper by an ephemeral ECDH key. Noise boxes are "one-way" - they can be decrypted by the receiver, but not the sender.
In more detail: Noise boxes consist of an ephemeral public key, followed by the sender's public key encrypted using the ECDH between the ephemeral and receiver keys. Following this, there's a payload encrypted using both the (ephemeral, receiver) ECDH and the (sender, receiver) ECDH:
(A',a') : ephemeral public key A' and private key a' (A,a) : sender's public key A and private key a (B,b) : receiver's public key B and private key b '*' : EC point-scalar multiply '||' : concatenation of byte sequences ENCRYPT(k, m) : authenticated encryption of m with symmetric key k noise_box((A',a'), (A,a), B, plaintext): key1 = HASH(a' * B) key2 = HASH((a * B) || key1) return A' || ENCRYPT(key1, A) || ENCRYPT(key2, plaintext)
The ephemeral ECDH adds forward-secrecy and identity-hiding for the sender.
Noise pipes begin with a handshake based on a "triple-DH" key agreement. The client and server identities (their public keys) are encrypted using intermediate results:
(C,c) : client's public key C and private key c (S,s) : server's public key S and private key s (C',c') : client's ephemeral public key C' and private key c' (S',s') : server's ephemeral public key S' and private key s' Client -> Server : C' key1 = HASH(c' * S') key2 = HASH((c' * S) || key1) Client <- Server : S' || Encrypt(key1, S) || Encrypt(key2, optional_plaintext) key3 = HASH((c * S') || key2) Client -> Server : C' || Encrypt(key2, C) || Encrypt(key3, optional_plaintext)
The pipe handshake can be implemented as an exchange of Noise boxes. The boxes are extended to support a "chaining variable" (CV) input which is used in deriving secret keys, and a CV output which is based on the box's secret keys. CVs are used to connect the boxes into a pipe handshake. The output from the first box is the input to the second box:
Client -> Server : C' Client <- Server : noise_box((S',s'), (S,s), C', optional_plaintext) # outputs chain_h1 Client -> Server : noise_box((C',c'), (C,c), S', optional_plaintext, chain_h1) # outputs chain_h2 session_key = chain_h2
Noise ciphersuites can be defined to use any DH or ECDH domain parameters. By default, Noise supports ECDH using Curve25519 and the Goldilocks-448 elliptic curve.
Noise boxes are a "hybrid" or "KEM/DEM" encryption of a plaintext, where the "KEM" is supplied by a "one-pass key agreement" protocol. The one-pass key agreement is a "one-pass unified model" ECDH, as sketched above.
Noise pipes begin with a Triple Diffie-Hellman key agreement, as sketched above. This key agreement is similar to the variant of "Protocol 1" from Kudla and Paterson, section 5.1 where forward-secrecy is added via a DH between the two ephemeral keys. However, the parties' identities are encrypted, accomplishing "identity-hiding" in the style of SIGMA-I. Since signatures are not used, Noise offers smaller messages, simpler cryptography, and stronger deniability than SIGMA-I.
Key derivation from ECDH results is done using HMAC-SHA2-512 in a manner inspired by HKDF-Expand.
Noise ciphersuites can be defined to use any authentication encryption algorithm. Currently ciphersuites are defined for ChaCha20/Poly1305 and AES-GCM.