2016-11-30 21:42:22 +01:00
# BOLT #8: Encrypted and Authenticated Transport
2016-11-29 01:48:29 +01:00
All communications between Lightning nodes is encrypted in order to
2017-12-08 01:16:24 +01:00
provide confidentiality for all transcripts between nodes and is authenticated in order to
avoid malicious interference. Each node has a known long-term identifier that
2016-11-15 02:23:20 +01:00
is a public key on Bitcoin's `secp256k1` curve. This long-term public key is
2017-12-08 01:16:24 +01:00
used within the protocol to establish an encrypted and authenticated connection
2016-12-09 01:02:23 +01:00
with peers, and also to authenticate any information advertised on behalf
2016-11-15 02:23:20 +01:00
of a node.
2017-12-08 19:58:08 +01:00
# Table of Contents
* [Cryptographic Messaging Overview ](#cryptographic-messaging-overview )
* [Authenticated Key Agreement Handshake ](#authenticated-key-agreement-handshake )
* [Handshake Versioning ](#handshake-versioning )
* [Noise Protocol Instantiation ](#noise-protocol-instantiation )
* [Authenticated Key Exchange Handshake Specification ](#authenticated-key-exchange-handshake-specification )
* [Handshake State ](#handshake-state )
* [Handshake State Initialization ](#handshake-state-initialization )
* [Handshake Exchange ](#handshake-exchange )
* [Lightning Message Specification ](#lightning-message-specification )
* [Encrypting Messages ](#encrypting-messages )
* [Decrypting Messages ](#decrypting-messages )
* [Lightning Message Key Rotation ](#lightning-message-key-rotation )
* [Security Considerations ](#security-considerations )
* [Appendix A: Transport Test Vectors ](#appendix-a-transport-test-vectors )
* [Initiator Tests ](#initiator-tests )
* [Responder Tests ](#responder-tests )
* [Message Encryption Tests ](#message-encryption-tests )
* [Acknowledgments ](#acknowledgments )
* [References ](#references )
* [Authors ](#authors )
2016-11-15 02:23:20 +01:00
## Cryptographic Messaging Overview
2017-12-08 01:16:24 +01:00
Prior to sending any Lightning messages, nodes must first initiate the
cryptographic session state that is used to encrypt and authenticate all
2016-11-15 02:23:20 +01:00
messages sent between nodes. The initialization of this cryptographic session
state is completely distinct from any inner protocol message header or
conventions.
The transcript between two nodes is separated into two distinct segments:
1. First, before any actual data transfer, both nodes participate in an
2017-12-27 23:30:21 +01:00
authenticated key agreement handshake, which is based on the Noise
2017-02-23 09:38:15 +01:00
Protocol Framework< sup > [2](#reference-2)< / sup > .
2017-12-08 01:16:24 +01:00
2. If the initial handshake is successful, then nodes enter the Lightning
message exchange phase. In the Lightning message exchange phase, all
messages are Authenticated Encryption with Associated Data (AEAD) ciphertexts.
2016-11-15 02:23:20 +01:00
### Authenticated Key Agreement Handshake
2017-12-08 19:58:08 +01:00
The handshake chosen for the authenticated key exchange is `Noise_XK` . As a
pre-message, the initiator must know the identity public key of
2017-12-08 01:16:24 +01:00
the responder. This provides a degree of identity hiding for the
responder, as its public key is _never_ transmitted during the handshake. Instead,
authentication is achieved implicitly via a series of Elliptic-Curve
Diffie-Hellman (ECDH) operations followed by a MAC check.
2016-11-15 02:23:20 +01:00
The authenticated key agreement (`Noise_XK`) is performed in three distinct
2017-12-08 19:58:08 +01:00
steps. During each "act" of the handshake the following occurs: some (possibly encrypted) keying
2017-12-08 01:16:24 +01:00
material is sent to the other party; an ECDH is performed based on exactly
which act is being executed, with the result mixed into the current set of
encryption keys (`ck` the chaining key and `k` the encryption key); and
2017-12-08 19:58:08 +01:00
an AEAD payload with a zero-length cipher text is sent. As this payload has no length, only a MAC is sent across. The mixing of ECDH outputs into
2016-11-24 21:58:57 +01:00
a hash digest forms an incremental TripleDH handshake.
2016-11-15 02:23:20 +01:00
2016-11-24 21:58:57 +01:00
Using the language of the Noise Protocol, `e` and `s` (both public keys)
2017-12-08 01:16:24 +01:00
indicate possibly encrypted keying material, and `es` , `ee` , and `se` each indicate an
ECDH operation between two keys. The handshake is laid out as follows:
```
2016-11-15 02:23:20 +01:00
Noise_XK(s, rs):
< - s
...
-> e, es
< - e , ee
-> s, se
2017-12-08 01:16:24 +01:00
```
2016-12-09 01:02:23 +01:00
All of the handshake data sent across the wire, including the keying material, is
2016-11-15 02:23:20 +01:00
incrementally hashed into a session-wide "handshake digest", `h` . Note that the
2017-12-08 01:16:24 +01:00
handshake state `h` , is never transmitted during the handshake; instead, digest
2017-09-22 08:03:40 +02:00
is used as the Associated Data within the zero-length AEAD messages.
2016-11-15 02:23:20 +01:00
2017-12-08 01:16:24 +01:00
Authenticating each message sent ensures that a man-in-the-middle (MITM) hasn't modified
or replaced any of the data sent as part of a handshake, as the MAC
2016-11-15 02:23:20 +01:00
check would fail on the other side if so.
2017-12-08 01:16:24 +01:00
A successful check of the MAC by the receiver indicates implicitly that all
authentication has been successful up to that point. If a MAC check ever fails
2016-11-15 02:23:20 +01:00
during the handshake process, then the connection is to be immediately
terminated.
2017-12-08 01:16:24 +01:00
### Handshake Versioning
2016-11-15 02:23:20 +01:00
Each message sent during the initial handshake starts with a single leading
2017-12-08 01:16:24 +01:00
byte, which indicates the version used for the current handshake. A version of 0
indicates that no change is necessary, while a non-zero version indicate that the
2016-11-15 02:23:20 +01:00
client has deviated from the protocol originally specified within this
document. Clients MUST reject handshake attempts initiated with an unknown
version.
### Noise Protocol Instantiation
2016-11-23 03:50:27 +01:00
Concrete instantiations of the Noise Protocol require the definition of
2016-11-15 02:23:20 +01:00
three abstract cryptographic objects: the hash function, the elliptic curve,
2017-12-08 01:16:24 +01:00
and the AEAD cipher scheme. For Lightning, `SHA-256` is
chosen as the hash function, `secp256k1` as the elliptic curve, and
`ChaChaPoly-1305` as the AEAD construction. The composition of `ChaCha20`
and `Poly1305` that are used MUST conform to `RFC 7539` < sup > [1](#reference-1)</ sup > .
The official protocol name for the Lightning variant of Noise is
`Noise_XK_secp256k1_ChaChaPoly_SHA256` . The ASCII string representation of
2016-11-15 02:23:20 +01:00
this value is hashed into a digest used to initialize the starting handshake
2016-12-09 01:02:23 +01:00
state. If the protocol names of two endpoints differ, then the handshake
2016-11-15 02:23:20 +01:00
process fails immediately.
## Authenticated Key Exchange Handshake Specification
The handshake proceeds in three acts, taking 1.5 round trips. Each handshake is
a _fixed_ sized payload without any header or additional meta-data attached.
The exact size of each Act is as follows:
2017-12-08 01:16:24 +01:00
* **Act One**: 50 bytes
* **Act Two**: 50 bytes
* **Act Three**: 66 bytes
2016-11-15 02:23:20 +01:00
### Handshake State
2016-12-06 04:09:11 +01:00
Throughout the handshake process, each side maintains these variables:
2016-11-15 02:23:20 +01:00
* `ck` : The **chaining key** . This value is the accumulated hash of all
previous ECDH outputs. At the end of the handshake, `ck` is used to derive
2017-12-08 01:16:24 +01:00
the encryption keys for Lightning messages.
2016-11-15 02:23:20 +01:00
* `h` : The **handshake hash** . This value is the accumulated hash of _all_
handshake data that has been sent and received so far during the handshake
process.
2017-12-08 01:16:24 +01:00
* `temp_k1` , `temp_k2` , `temp_k3` : **intermediate keys** . These are used to encrypt and decrypt the
2016-11-15 02:23:20 +01:00
zero-length AEAD payloads at the end of each handshake message.
2016-12-06 04:09:11 +01:00
* `e` : A party's **ephemeral keypair** . For each session a node MUST generate a
2016-11-15 02:23:20 +01:00
new ephemeral key with strong cryptographic randomness.
2017-12-08 22:00:22 +01:00
* `s` : a party's **static public key** (`ls` for local, `rs` for remote)
2016-11-15 02:23:20 +01:00
The following functions will also be referenced:
2017-12-08 01:16:24 +01:00
* `ECDH(rk, k)` : performs an Elliptic-Curve Diffie-Hellman operation using
`rk` , which is a `secp256k1` public key, and `k` , which is a valid private key
within the finite field as defined by the curve parameters
* The returned value is the SHA256 of the DER-compressed format of the
2016-12-12 01:11:45 +01:00
generated point.
2016-11-24 21:58:57 +01:00
2017-12-08 01:16:24 +01:00
* `HKDF(salt,ikm)` : a function defined in [3 ](#reference-3 ), evaluated with a
zero-length `info` field
* All invocations of `HKDF` implicitly return 64 bytes of
2016-11-24 21:58:57 +01:00
cryptographic randomness using the extract-and-expand component of the
2016-12-06 04:09:11 +01:00
`HKDF` .
2016-11-24 21:58:57 +01:00
2016-12-08 01:25:42 +01:00
* `encryptWithAD(k, n, ad, plaintext)` : outputs `encrypt(k, n, ad, plaintext)`
2016-12-06 04:09:31 +01:00
* where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant) with the passed
2017-12-08 01:16:24 +01:00
arguments, with nonce `n` encoded as 32 zero bits, followed by a *little-endian* 64-bit value (this
2016-12-22 02:01:38 +01:00
follows the Noise Protocol convention, rather than our normal endian).
2016-12-08 01:25:42 +01:00
* `decryptWithAD(k, n, ad, ciphertext)` : outputs `decrypt(k, n, ad, ciphertext)`
2016-12-06 04:09:31 +01:00
* where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant) with the passed
2017-12-08 01:16:24 +01:00
arguments, with nonce `n` encoded as 32 zero bits, followed by a *little-endian* 64-bit value.
2016-11-24 21:58:57 +01:00
2017-12-08 01:16:24 +01:00
* `generateKey()` : generates and returns a fresh `secp256k1` keypair
* where the object returned by `generateKey` has two attributes:
* `.pub` , which returns an abstract object representing the public key
* `.priv` , which represents the private key used to generate the
2016-11-24 21:58:57 +01:00
public key
2017-12-08 01:16:24 +01:00
* where the object also has a single method:
2016-11-24 21:58:57 +01:00
* `.serializeCompressed()`
2016-11-15 02:23:20 +01:00
* `a || b` denotes the concatenation of two byte strings `a` and `b`
### Handshake State Initialization
Before the start of the first act, both sides initialize their per-sessions
state as follows:
2016-11-24 21:58:57 +01:00
1. `h = SHA-256(protocolName)`
2016-11-15 02:23:20 +01:00
* where `protocolName = "Noise_XK_secp256k1_ChaChaPoly_SHA256"` encoded as
2017-05-02 09:23:46 +02:00
an ASCII string.
2016-11-15 02:23:20 +01:00
2016-11-24 21:58:57 +01:00
2. `ck = h`
2016-11-15 02:23:20 +01:00
2016-12-08 01:26:15 +01:00
3. `h = SHA-256(h || prologue)`
2017-05-02 09:23:46 +02:00
* where `prologue` is the ASCII string: `lightning` .
2016-11-15 02:23:20 +01:00
As a concluding step, both sides mix the responder's public key into the
handshake digest:
* The initiating node mixes in the responding node's static public key
2017-12-08 01:16:24 +01:00
serialized in Bitcoin's DER-compressed format:
2016-11-24 21:58:57 +01:00
* `h = SHA-256(h || rs.pub.serializeCompressed())`
2016-11-15 02:23:20 +01:00
* The responding node mixes in their local static public key serialized in
2017-12-08 01:16:24 +01:00
Bitcoin's DER-compressed format:
2016-11-24 21:58:57 +01:00
* `h = SHA-256(h || ls.pub.serializeCompressed())`
2016-11-15 02:23:20 +01:00
### Handshake Exchange
#### Act One
```
-> e, es
```
2017-12-08 01:16:24 +01:00
Act One is sent from initiator to responder. During Act One, the initiator
2016-11-15 02:23:20 +01:00
attempts to satisfy an implicit challenge by the responder. To complete this
challenge, the initiator _must_ know the static public key of the responder.
2017-12-08 01:16:24 +01:00
The handshake message is _exactly_ 50 bytes: 1 byte for the handshake
version, 33 bytes for the compressed ephemeral public key of the initiator,
and 16 bytes for the `poly1305` tag.
2016-11-15 02:23:20 +01:00
**Sender Actions:**
2018-01-01 23:55:04 +01:00
1. `e = generateKey()`
2018-01-30 04:40:05 +01:00
2. `h = SHA-256(h || e.pub.serializeCompressed())`
2017-12-08 01:16:24 +01:00
* The newly generated ephemeral key is accumulated into the running
2016-11-15 02:23:20 +01:00
handshake digest.
2018-01-30 04:40:05 +01:00
3. `ss = ECDH(rs, e.priv)`
2017-12-08 01:16:24 +01:00
* The initiator performs an ECDH between its newly generated ephemeral
key and the remote node's static public key.
2018-01-30 04:40:05 +01:00
4. `ck, temp_k1 = HKDF(ck, ss)`
2017-12-08 01:16:24 +01:00
* A new temporary encryption key is generated, which is
2016-11-15 02:23:20 +01:00
used to generate the authenticating MAC.
2018-01-30 04:40:05 +01:00
5. `c = encryptWithAD(temp_k1, 0, h, zero)`
2016-11-15 02:23:20 +01:00
* where `zero` is a zero-length plaintext
2018-01-30 04:40:05 +01:00
6. `h = SHA-256(h || c)`
2016-11-15 02:23:20 +01:00
* Finally, the generated ciphertext is accumulated into the authenticating
handshake digest.
2018-01-30 04:40:05 +01:00
7. Send `m = 0 || e.pub.serializeCompressed() || c` to the responder over the network buffer.
2016-11-15 02:23:20 +01:00
**Receiver Actions:**
2018-01-01 23:55:04 +01:00
1. Read _exactly_ 50 bytes from the network buffer.
2018-01-30 04:40:05 +01:00
2. Parse out the read message (`m`) into `v = m[0]` , `re = m[1:33]` , and `c = m[34:]` .
2017-12-08 01:16:24 +01:00
* where `m[0]` is the _first_ byte of `m` , `m[1:33]` is the next 33
bytes of `m` , and `m[34:]` is the last 16 bytes of `m`
2016-11-24 21:58:57 +01:00
* The raw bytes of the remote party's ephemeral public key (`e`) are to be
deserialized into a point on the curve using affine coordinates as encoded
by the key's serialized composed format.
2018-01-30 04:40:05 +01:00
3. If `v` is an unrecognized handshake version, then the responder MUST
2016-11-15 02:23:20 +01:00
abort the connection attempt.
2018-01-30 04:40:05 +01:00
4. `h = SHA-256(h || re.serializeCompressed())`
2017-12-08 01:16:24 +01:00
* The responder accumulates the initiator's ephemeral key into the authenticating
2016-11-15 02:23:20 +01:00
handshake digest.
2018-01-30 04:40:05 +01:00
5. `ss = ECDH(re, s.priv)`
2017-12-08 01:16:24 +01:00
* The responder performs an ECDH between its static public key and the
2016-11-15 02:23:20 +01:00
initiator's ephemeral public key.
2018-01-30 04:40:05 +01:00
6. `ck, temp_k1 = HKDF(ck, ss)`
2017-12-08 01:16:24 +01:00
* A new temporary encryption key is generated, which will
shortly be used to check the authenticating MAC.
2018-01-30 04:40:05 +01:00
7. `p = decryptWithAD(temp_k1, 0, h, c)`
2016-11-15 02:23:20 +01:00
* If the MAC check in this operation fails, then the initiator does _not_
2017-12-08 01:16:24 +01:00
know the responder's static public key. If so, then the responder MUST terminate the
2016-11-15 02:23:20 +01:00
connection without any further messages.
2018-01-30 04:40:05 +01:00
8. `h = SHA-256(h || c)`
2017-12-08 01:16:24 +01:00
* The received ciphertext is mixed into the handshake digest. This step serves
2016-11-15 02:23:20 +01:00
to ensure the payload wasn't modified by a MiTM.
#### Act Two
```
< - e , ee
```
2017-12-08 01:16:24 +01:00
Act Two is sent from the responder to the initiator. Act Two will _only_
take place if Act One was successful. Act One was successful if the
responder was able to properly decrypt and check the MAC of the tag sent at
the end of Act One.
2016-11-15 02:23:20 +01:00
2017-12-08 01:16:24 +01:00
The handshake is _exactly_ 50 bytes: 1 byte for the handshake version, 33
bytes for the compressed ephemeral public key of the responder, and 16 bytes
2016-11-15 02:23:20 +01:00
for the `poly1305` tag.
**Sender Actions:**
2018-01-01 23:55:04 +01:00
1. `e = generateKey()`
2018-01-30 04:40:05 +01:00
2. `h = SHA-256(h || e.pub.serializeCompressed())`
2017-12-08 01:16:24 +01:00
* The newly generated ephemeral key is accumulated into the running
2016-11-15 02:23:20 +01:00
handshake digest.
2018-01-30 04:40:05 +01:00
3. `ss = ECDH(re, e.priv)`
2017-12-08 01:16:24 +01:00
* where `re` is the ephemeral key of the initiator, which was received
during Act One
2018-01-30 04:40:05 +01:00
4. `ck, temp_k2 = HKDF(ck, ss)`
2017-12-08 01:16:24 +01:00
* A new temporary encryption key is generated, which is
2016-11-15 02:23:20 +01:00
used to generate the authenticating MAC.
2018-01-30 04:40:05 +01:00
5. `c = encryptWithAD(temp_k2, 0, h, zero)`
2016-11-15 02:23:20 +01:00
* where `zero` is a zero-length plaintext
2018-01-30 04:40:05 +01:00
6. `h = SHA-256(h || c)`
2016-11-15 02:23:20 +01:00
* Finally, the generated ciphertext is accumulated into the authenticating
handshake digest.
2018-01-30 04:40:05 +01:00
7. Send `m = 0 || e.pub.serializeCompressed() || c` to the initiator over the network buffer.
2016-11-15 02:23:20 +01:00
**Receiver Actions:**
2018-01-01 23:55:04 +01:00
1. Read _exactly_ 50 bytes from the network buffer.
2018-01-30 04:40:05 +01:00
2. Parse out the read message (`m`) into `v = m[0]` , `re = m[1:33]` , and `c = m[34:]` .
2017-12-08 01:16:24 +01:00
* where `m[0]` is the _first_ byte of `m` , `m[1:33]` is the next 33
bytes of `m` , and `m[34:]` is the last 16 bytes of `m`
2018-01-30 04:40:05 +01:00
3. If `v` is an unrecognized handshake version, then the responder MUST
2016-11-15 02:23:20 +01:00
abort the connection attempt.
2018-01-30 04:40:05 +01:00
4. `h = SHA-256(h || re.serializeCompressed())`
5. `ss = ECDH(re, e.priv)`
2017-12-08 01:16:24 +01:00
* where `re` is the responder's ephemeral public key
2016-12-06 04:09:11 +01:00
* The raw bytes of the remote party's ephemeral public key (`re`) are to be
2016-11-24 21:58:57 +01:00
deserialized into a point on the curve using affine coordinates as encoded
by the key's serialized composed format.
2018-01-30 04:40:05 +01:00
6. `ck, temp_k2 = HKDF(ck, ss)`
2017-12-08 01:16:24 +01:00
* A new temporary encryption key is generated, which is
2016-11-15 02:23:20 +01:00
used to generate the authenticating MAC.
2018-01-30 04:40:05 +01:00
7. `p = decryptWithAD(temp_k2, 0, h, c)`
2016-11-15 02:23:20 +01:00
* If the MAC check in this operation fails, then the initiator MUST
terminate the connection without any further messages.
2018-01-30 04:40:05 +01:00
8. `h = SHA-256(h || c)`
2017-12-08 01:16:24 +01:00
* The received ciphertext is mixed into the handshake digest. This step serves
2016-11-15 02:23:20 +01:00
to ensure the payload wasn't modified by a MiTM.
#### Act Three
```
-> s, se
```
2017-12-08 01:16:24 +01:00
Act Three is the final phase in the authenticated key agreement described in
this section. This act is sent from the initiator to the responder as a
concluding step. Act Three is executed _if and only if_ Act Two was successful.
During Act Three, the initiator transports its static public key to the
responder encrypted with _strong_ forward secrecy, using the accumulated `HKDF`
2016-11-15 02:23:20 +01:00
derived secret key at this point of the handshake.
2017-12-08 01:16:24 +01:00
The handshake is _exactly_ 66 bytes: 1 byte for the handshake version, 33
bytes for the ephemeral public key encrypted with the `ChaCha20` stream
cipher, 16 bytes for the encrypted public key's tag generated via the AEAD
construction, and 16 bytes for a final authenticating tag.
2016-11-15 02:23:20 +01:00
**Sender Actions:**
2018-01-01 23:55:04 +01:00
1. `c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())`
2017-12-08 01:16:24 +01:00
* where `s` is the static public key of the initiator
2018-01-30 04:40:05 +01:00
2. `h = SHA-256(h || c)`
3. `ss = ECDH(re, s.priv)`
2016-11-15 02:23:20 +01:00
* where `re` is the ephemeral public key of the responder.
2018-01-30 04:40:05 +01:00
4. `ck, temp_k3 = HKDF(ck, ss)`
2017-12-08 01:16:24 +01:00
* The final intermediate shared secret is mixed into the running chaining key.
2018-01-30 04:40:05 +01:00
5. `t = encryptWithAD(temp_k3, 0, h, zero)`
2016-11-15 02:23:20 +01:00
* where `zero` is a zero-length plaintext
2018-01-30 04:40:05 +01:00
6. `sk, rk = HKDF(ck, zero)`
2016-11-15 02:23:20 +01:00
* where `zero` is a zero-length plaintext,
`sk` is the key to be used by the initiator to encrypt messages to the
responder,
and `rk` is the key to be used by the initiator to decrypt messages sent by
2017-12-08 01:16:24 +01:00
the responder
* The final encryption keys to be used for sending and
receiving messages for the duration of the session are generated.
2018-01-30 04:40:05 +01:00
7. `rn = 0, sn = 0`
2016-12-06 06:35:49 +01:00
* The sending and receiving nonces are initialized to zero.
2018-01-30 04:40:05 +01:00
8. Send `m = 0 || c || t` over the network buffer.
2016-11-15 02:23:20 +01:00
**Receiver Actions:**
2018-01-01 23:55:04 +01:00
1. Read _exactly_ 66 bytes from the network buffer.
2018-01-30 04:40:05 +01:00
2. Parse out the read message (`m`) into `v = m[0]` , `c = m[1:49]` and `t = m[50:]`
3. If `v` is an unrecognized handshake version, then the responder MUST
2016-11-15 02:23:20 +01:00
abort the connection attempt.
2018-01-30 04:40:05 +01:00
4. `rs = decryptWithAD(temp_k2, 1, h, c)`
2016-11-15 02:23:20 +01:00
* At this point, the responder has recovered the static public key of the
initiator.
2018-01-30 04:40:05 +01:00
5. `h = SHA-256(h || c)`
6. `ss = ECDH(rs, e.priv)`
2016-11-15 02:23:20 +01:00
* where `e` is the responder's original ephemeral key
2018-01-30 04:40:05 +01:00
7. `ck, temp_k3 = HKDF(ck, ss)`
8. `p = decryptWithAD(temp_k3, 0, h, t)`
2016-11-15 02:23:20 +01:00
* If the MAC check in this operation fails, then the responder MUST
terminate the connection without any further messages.
2018-01-30 04:40:05 +01:00
9. `rk, sk = HKDF(ck, zero)`
2016-11-15 02:23:20 +01:00
* where `zero` is a zero-length plaintext,
`rk` is the key to be used by the responder to decrypt the messages sent
2016-12-06 06:24:21 +01:00
by the initiator,
and `sk` is the key to be used by the responder to encrypt messages to
2017-12-08 01:16:24 +01:00
the initiator
* The final encryption keys to be used for sending and
2017-12-08 19:58:08 +01:00
receiving messages for the duration of the session are generated.
2018-01-30 04:40:05 +01:00
10. `rn = 0, sn = 0`
2016-12-06 06:35:49 +01:00
* The sending and receiving nonces are initialized to zero.
2016-11-29 01:48:29 +01:00
## Lightning Message Specification
2016-11-15 02:23:20 +01:00
2017-12-08 01:16:24 +01:00
At the conclusion of Act Three, both sides have derived the encryption keys, which will be used to encrypt and decrypt messages for the remainder of the
2016-11-15 02:23:20 +01:00
session.
2017-12-08 01:16:24 +01:00
The actual Lightning protocol messages are encapsulated within AEAD ciphertexts. Each message is prefixed with
another AEAD ciphertext, which encodes the total length of the following Lightning
2016-11-29 01:48:29 +01:00
message (not counting its MAC).
2017-12-08 01:16:24 +01:00
The *maximum* size of _any_ Lightning message MUST NOT exceed `65535` bytes. A
BOLT 1, BOLT 2, BOLT 5: 2-byte lengths everywhere.
Since our cryptopacket limits us to 2 bytes, and since people will
send 1-message-per-crypto-packet and nobody will test the
multiple-messages-in-one-cryptopacket code, let's just restrict to
64k messages.
1. Make cryptopacket length not include the HMAC, so we can actually send
64k messages.
2. Remove len prefix from packet, make type 2 bytes, note alignment properties.
3. Change message internal lengths/counts from 4 to 2 bytes, since more
is nonsensical anyway, and this removes a need to check before allocating:
- init feature bitfield length
- error message length
- shutdown scriptpubkey length
- commit_sig number of HTLC signatures
- revoke_and_ack number of HTLC-timeout signatures
4. Change max-accepted-htlcs to two bytes, and limit it to 511 to ensure
that commit_sig will always be under 64k.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2016-11-24 05:58:30 +01:00
maximum size of `65535` simplifies testing, makes memory management
2017-12-08 01:16:24 +01:00
easier, and helps mitigate memory-exhaustion attacks.
2016-11-15 02:23:20 +01:00
2017-12-08 20:07:16 +01:00
In order to make traffic analysis more difficult, the length prefix for
2017-12-08 01:16:24 +01:00
all encrypted Lightning messages is also encrypted. Additionally a
16-byte `Poly-1305` tag is added to the encrypted length prefix in order to ensure
that the packet length hasn't been modified when in-flight and also to avoid
2016-11-15 02:23:20 +01:00
creating a decryption oracle.
2016-11-29 01:48:29 +01:00
The structure of packets on the wire resembles the following:
2016-11-15 02:23:20 +01:00
```
2016-11-29 01:48:29 +01:00
+-------------------------------
|2-byte encrypted message length|
+-------------------------------
| 16-byte MAC of the encrypted |
| message length |
+-------------------------------
| |
| |
2017-12-08 01:16:24 +01:00
| encrypted Lightning |
2016-11-29 01:48:29 +01:00
| message |
| |
+-------------------------------
| 16-byte MAC of the |
2017-12-08 01:16:24 +01:00
| Lightning message |
2016-11-29 01:48:29 +01:00
+-------------------------------
2016-11-15 02:23:20 +01:00
```
2017-12-08 01:16:24 +01:00
The prefixed message length is encoded as a 2-byte big-endian integer,
2016-11-29 01:48:29 +01:00
for a total maximum packet length of `2 + 16 + 65535 + 16` = `65569` bytes.
2016-11-15 02:23:20 +01:00
### Encrypting Messages
2017-12-08 01:16:24 +01:00
In order to encrypt a Lightning message (`m`), given a sending key (`sk`) and a nonce
2016-12-06 06:35:49 +01:00
(`sn`), the following is done:
2016-11-15 02:23:20 +01:00
2018-01-01 23:55:04 +01:00
1. let `l = len(m)`
2017-12-08 01:16:24 +01:00
* where `len` obtains the length in bytes of the Lightning message
2018-01-30 04:40:05 +01:00
2. Serialize `l` into 2 bytes encoded as a big-endian integer.
3. Encrypt `l` (using `ChaChaPoly-1305` , `sn` , and `sk` ), to obtain `lc`
2017-12-08 01:16:24 +01:00
(18 bytes)
* The nonce `sn` is encoded as a 96-bit little-endian number. As the
decoded nonce is 64 bits, the 96-bit nonce is encoded as: 32 bits
2017-01-06 22:54:51 +01:00
of leading zeroes followed by a 64-bit value.
* The nonce `sn` MUST be incremented after this step.
2016-11-24 21:58:57 +01:00
* A zero-length byte slice is to be passed as the AD (associated data).
2018-01-30 04:40:05 +01:00
4. Finally, encrypt the message itself (`m`) using the same procedure used to
2016-11-15 02:23:20 +01:00
encrypt the length prefix. Let encrypted ciphertext be known as `c` .
2016-12-06 06:35:49 +01:00
* The nonce `sn` MUST be incremented after this step.
2018-01-30 04:40:05 +01:00
5. Send `lc || c` over the network buffer.
2016-11-15 02:23:20 +01:00
### Decrypting Messages
In order to decrypt the _next_ message in the network stream, the following is
done:
2018-01-01 23:55:04 +01:00
1. Read _exactly_ 18 bytes from the network buffer.
2018-01-30 04:40:05 +01:00
2. Let the encrypted length prefix be known as `lc`
3. Decrypt `lc` (using `ChaCha20-Poly1305` , `rn` , and `rk` ), to obtain the size of
2016-11-24 21:58:57 +01:00
the encrypted packet `l` .
* A zero-length byte slice is to be passed as the AD (associated data).
2016-12-06 06:35:49 +01:00
* The nonce `rn` MUST be incremented after this step.
2018-01-30 04:40:05 +01:00
4. Read _exactly_ `l+16` bytes from the network buffer, let the bytes be known as
2016-11-15 02:23:20 +01:00
`c` .
2018-01-30 04:40:05 +01:00
5. Decrypt `c` (using `ChaCha20-Poly1305` , `rn` , and `rk` ), to obtain decrypted
2016-11-15 02:23:20 +01:00
plaintext packet `p` .
2016-12-06 06:35:49 +01:00
* The nonce `rn` MUST be incremented after this step.
2016-11-15 02:23:20 +01:00
2016-11-29 01:48:29 +01:00
## Lightning Message Key Rotation
2016-11-15 02:23:20 +01:00
2017-12-08 01:16:24 +01:00
Changing keys regularly and forgetting previous keys is useful to
2017-12-08 19:58:08 +01:00
prevent the decryption of old messages, in the case of later key leakage (i.e.
2016-11-15 02:23:20 +01:00
backwards secrecy).
2017-12-08 01:16:24 +01:00
Key rotation is performed for _each_ key (`sk` and `rk` ) _individually_ . A key
is to be rotated after a party sends or decrypts 1000 messages with it.
2016-11-15 02:23:20 +01:00
This can be properly accounted for by rotating the key once the nonce dedicated
2017-12-08 01:16:24 +01:00
to it exceeds 1000.
2016-11-15 02:23:20 +01:00
Key rotation for a key `k` is performed according to the following:
2018-01-01 23:55:04 +01:00
1. Let `ck` be the chaining key obtained at the end of Act Three.
2018-01-30 04:40:05 +01:00
2. `ck', k' = HKDF(ck, k)`
3. Reset the nonce for the key to `n = 0` .
4. `k = k'`
5. `ck = ck'`
2016-11-30 21:05:50 +01:00
2017-12-08 01:16:24 +01:00
# Security Considerations
2016-11-15 02:23:20 +01:00
It is strongly recommended that existing, commonly-used, validated
libraries be used for encryption and decryption, to avoid the many
implementation pitfalls possible.
2016-12-22 02:01:51 +01:00
# Appendix A: Transport Test Vectors
2017-12-08 01:16:24 +01:00
To make a repeatable test handshake, the following specifies what `generateKey()` will
return (i.e. the value for `e.priv` ) for each side. Note that this
is a violation of the spec, which requires randomness.
2016-12-22 02:01:51 +01:00
## Initiator Tests
The initiator should produce the given output when fed this input.
The comments reflect internal state for debugging.
2017-12-08 01:16:24 +01:00
```
2016-12-22 02:01:51 +01:00
name: transport-initiator successful handshake
rs.pub: 0x028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
ls.priv: 0x1111111111111111111111111111111111111111111111111111111111111111
ls.pub: 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
e.priv: 0x1212121212121212121212121212121212121212121212121212121212121212
e.pub: 0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
# Act One
# h=0x9e0e7de8bb75554f21db034633de04be41a2b8a18da7a319a03c803bf02b396c
# ss=0x1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3
# HKDF(0x2640f52eebcd9e882958951c794250eedb28002c05d7dc2ea0f195406042caf1,0x1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3)
# ck,temp_k1=0xb61ec1191326fa240decc9564369dbb3ae2b34341d1e11ad64ed89f89180582f,0xe68f69b7f096d7917245f5e5cf8ae1595febe4d4644333c99f9c4a1282031c9f
# encryptWithAD(0xe68f69b7f096d7917245f5e5cf8ae1595febe4d4644333c99f9c4a1282031c9f, 0x000000000000000000000000, 0x9e0e7de8bb75554f21db034633de04be41a2b8a18da7a319a03c803bf02b396c, < empty > )
# c=0df6086551151f58b8afe6c195782c6a
# h=0x9d1ffbb639e7e20021d9259491dc7b160aab270fb1339ef135053f6f2cebe9ce
output: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
input: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# re=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# h=0x38122f669819f906000621a14071802f93f2ef97df100097bcac3ae76c6dc0bf
# ss=0xc06363d6cc549bcb7913dbb9ac1c33fc1158680c89e972000ecd06b36c472e47
# HKDF(0xb61ec1191326fa240decc9564369dbb3ae2b34341d1e11ad64ed89f89180582f,0xc06363d6cc549bcb7913dbb9ac1c33fc1158680c89e972000ecd06b36c472e47)
# ck,temp_k2=0xe89d31033a1b6bf68c07d22e08ea4d7884646c4b60a9528598ccb4ee2c8f56ba,0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc
# decryptWithAD(0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc, 0x000000000000000000000000, 0x38122f669819f906000621a14071802f93f2ef97df100097bcac3ae76c6dc0bf, 0x6e2470b93aac583c9ef6eafca3f730ae)
# h=0x90578e247e98674e661013da3c5c1ca6a8c8f48c90b485c0dfa1494e23d56d72
# Act Three
# encryptWithAD(0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc, 0x000000000100000000000000, 0x90578e247e98674e661013da3c5c1ca6a8c8f48c90b485c0dfa1494e23d56d72, 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa)
# c=0xb9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c3822
# h=0x5dcb5ea9b4ccc755e0e3456af3990641276e1d5dc9afd82f974d90a47c918660
# ss=0xb36b6d195982c5be874d6d542dc268234379e1ae4ff1709402135b7de5cf0766
# HKDF(0xe89d31033a1b6bf68c07d22e08ea4d7884646c4b60a9528598ccb4ee2c8f56ba,0xb36b6d195982c5be874d6d542dc268234379e1ae4ff1709402135b7de5cf0766)
# ck,temp_k3=0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,0x981a46c820fb7a241bc8184ba4bb1f01bcdfafb00dde80098cb8c38db9141520
# encryptWithAD(0x981a46c820fb7a241bc8184ba4bb1f01bcdfafb00dde80098cb8c38db9141520, 0x000000000000000000000000, 0x5dcb5ea9b4ccc755e0e3456af3990641276e1d5dc9afd82f974d90a47c918660, < empty > )
# t=0x8dc68b1c466263b47fdf31e560e139ba
output: 0x00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba
# HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,zero)
output: sk,rk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9,0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442
name: transport-initiator act2 short read test
rs.pub: 0x028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
ls.priv: 0x1111111111111111111111111111111111111111111111111111111111111111
ls.pub: 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
e.priv: 0x1212121212121212121212121212121212121212121212121212121212121212
e.pub: 0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
output: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
input: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730
output: ERROR (ACT2_READ_FAILED)
name: transport-initiator act2 bad version test
rs.pub: 0x028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
ls.priv: 0x1111111111111111111111111111111111111111111111111111111111111111
ls.pub: 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
e.priv: 0x1212121212121212121212121212121212121212121212121212121212121212
e.pub: 0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
output: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
input: 0x0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
output: ERROR (ACT2_BAD_VERSION 1)
name: transport-initiator act2 bad key serialization test
rs.pub: 0x028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
ls.priv: 0x1111111111111111111111111111111111111111111111111111111111111111
ls.pub: 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
e.priv: 0x1212121212121212121212121212121212121212121212121212121212121212
e.pub: 0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
output: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
input: 0x0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
output: ERROR (ACT2_BAD_PUBKEY)
name: transport-initiator act2 bad MAC test
rs.pub: 0x028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
ls.priv: 0x1111111111111111111111111111111111111111111111111111111111111111
ls.pub: 0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
e.priv: 0x1212121212121212121212121212121212121212121212121212121212121212
e.pub: 0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
output: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
input: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af
output: ERROR (ACT2_BAD_TAG)
2017-12-08 01:16:24 +01:00
```
2016-12-22 02:01:51 +01:00
## Responder Tests
The responder should produce the given output when fed this input.
2017-12-08 01:16:24 +01:00
```
2016-12-22 02:01:51 +01:00
name: transport-responder successful handshake
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# re=0x036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7
# h=0x9e0e7de8bb75554f21db034633de04be41a2b8a18da7a319a03c803bf02b396c
# ss=0x1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3
# HKDF(0x2640f52eebcd9e882958951c794250eedb28002c05d7dc2ea0f195406042caf1,0x1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3)
# ck,temp_k1=0xb61ec1191326fa240decc9564369dbb3ae2b34341d1e11ad64ed89f89180582f,0xe68f69b7f096d7917245f5e5cf8ae1595febe4d4644333c99f9c4a1282031c9f
# decryptWithAD(0xe68f69b7f096d7917245f5e5cf8ae1595febe4d4644333c99f9c4a1282031c9f, 0x000000000000000000000000, 0x9e0e7de8bb75554f21db034633de04be41a2b8a18da7a319a03c803bf02b396c, 0x0df6086551151f58b8afe6c195782c6a)
# h=0x9d1ffbb639e7e20021d9259491dc7b160aab270fb1339ef135053f6f2cebe9ce
# Act Two
# e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27 e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
# h=0x38122f669819f906000621a14071802f93f2ef97df100097bcac3ae76c6dc0bf
# ss=0xc06363d6cc549bcb7913dbb9ac1c33fc1158680c89e972000ecd06b36c472e47
# HKDF(0xb61ec1191326fa240decc9564369dbb3ae2b34341d1e11ad64ed89f89180582f,0xc06363d6cc549bcb7913dbb9ac1c33fc1158680c89e972000ecd06b36c472e47)
# ck,temp_k2=0xe89d31033a1b6bf68c07d22e08ea4d7884646c4b60a9528598ccb4ee2c8f56ba,0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc
# encryptWithAD(0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc, 0x000000000000000000000000, 0x38122f669819f906000621a14071802f93f2ef97df100097bcac3ae76c6dc0bf, < empty > )
# c=0x6e2470b93aac583c9ef6eafca3f730ae
# h=0x90578e247e98674e661013da3c5c1ca6a8c8f48c90b485c0dfa1494e23d56d72
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba
# decryptWithAD(0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc, 0x000000000100000000000000, 0x90578e247e98674e661013da3c5c1ca6a8c8f48c90b485c0dfa1494e23d56d72, 0xb9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c3822)
# rs=0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
# h=0x5dcb5ea9b4ccc755e0e3456af3990641276e1d5dc9afd82f974d90a47c918660
# ss=0xb36b6d195982c5be874d6d542dc268234379e1ae4ff1709402135b7de5cf0766
# HKDF(0xe89d31033a1b6bf68c07d22e08ea4d7884646c4b60a9528598ccb4ee2c8f56ba,0xb36b6d195982c5be874d6d542dc268234379e1ae4ff1709402135b7de5cf0766)
# ck,temp_k3=0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,0x981a46c820fb7a241bc8184ba4bb1f01bcdfafb00dde80098cb8c38db9141520
# decryptWithAD(0x981a46c820fb7a241bc8184ba4bb1f01bcdfafb00dde80098cb8c38db9141520, 0x000000000000000000000000, 0x5dcb5ea9b4ccc755e0e3456af3990641276e1d5dc9afd82f974d90a47c918660, 0x8dc68b1c466263b47fdf31e560e139ba)
# HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,zero)
output: rk,sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9,0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442
name: transport-responder act1 short read test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c
output: ERROR (ACT1_READ_FAILED)
name: transport-responder act1 bad version test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
output: ERROR (ACT1_BAD_VERSION)
name: transport-responder act1 bad key serialization test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
output: ERROR (ACT1_BAD_PUBKEY)
name: transport-responder act1 bad MAC test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b
output: ERROR (ACT1_BAD_TAG)
name: transport-responder act3 bad version test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba
output: ERROR (ACT3_BAD_VERSION 1)
name: transport-responder act3 short read test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139
output: ERROR (ACT3_READ_FAILED)
name: transport-responder act3 bad MAC for ciphertext test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba
output: ERROR (ACT3_BAD_CIPHERTEXT)
name: transport-responder act3 bad rs test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c
# decryptWithAD(0x908b166535c01a935cf1e130a5fe895ab4e6f3ef8855d87e9b7581c4ab663ddc, 0x000000000000000000000001, 0x90578e247e98674e661013da3c5c1ca6a8c8f48c90b485c0dfa1494e23d56d72, 0xd7fedc211450dd9602b41081c9bd05328b8bf8c0238880f7b7cb8a34bb6d8354081e8d4b81887fae47a74fe8aab3008653)
# rs=0x044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
output: ERROR (ACT3_BAD_PUBKEY)
name: transport-responder act3 bad MAC test
ls.priv=2121212121212121212121212121212121212121212121212121212121212121
ls.pub=028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7
e.priv=0x2222222222222222222222222222222222222222222222222222222222222222
e.pub=0x02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27
# Act One
input: 0x00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a
# Act Two
output: 0x0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae
# Act Three
input: 0x00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb
output: ERROR (ACT3_BAD_TAG)
2017-12-08 01:16:24 +01:00
```
2017-01-04 06:22:25 +01:00
## Message Encryption Tests
In this test, the initiator sends length 5 messages containing "hello"
2017-12-08 01:16:24 +01:00
1001 times. Only six example outputs are shown, for brevity and to test
two key rotations:
2017-01-04 06:22:25 +01:00
name: transport-message test
ck=0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01
sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9
rk=0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442
2017-01-06 04:35:57 +01:00
# encrypt l: cleartext=0x0005, AD=NULL, sn=0x000000000000000000000000, sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9 => 0xcf2b30ddf0cf3f80e7c35a6e6730b59fe802
# encrypt m: cleartext=0x68656c6c6f, AD=NULL, sn=0x000000000100000000000000, sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9 => 0x473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95
output 0: 0xcf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95
# encrypt l: cleartext=0x0005, AD=NULL, sn=0x000000000200000000000000, sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9 => 0x72887022101f0b6753e0c7de21657d35a4cb
# encrypt m: cleartext=0x68656c6c6f, AD=NULL, sn=0x000000000300000000000000, sk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9 => 0x2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1
output 1: 0x72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1
# 0xcc2c6e467efc8067720c2d09c139d1f77731893aad1defa14f9bf3c48d3f1d31, 0x3fbdc101abd1132ca3a0ae34a669d8d9ba69a587e0bb4ddd59524541cf4813d8 = HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01, 0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9)
# 0xcc2c6e467efc8067720c2d09c139d1f77731893aad1defa14f9bf3c48d3f1d31, 0x3fbdc101abd1132ca3a0ae34a669d8d9ba69a587e0bb4ddd59524541cf4813d8 = HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01, 0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9)
output 500: 0x178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8
output 501: 0x1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd
# 0x728366ed68565dc17cf6dd97330a859a6a56e87e2beef3bd828a4c4a54d8df06, 0x9e0477f9850dca41e42db0e4d154e3a098e5a000d995e421849fcd5df27882bd = HKDF(0xcc2c6e467efc8067720c2d09c139d1f77731893aad1defa14f9bf3c48d3f1d31, 0x3fbdc101abd1132ca3a0ae34a669d8d9ba69a587e0bb4ddd59524541cf4813d8)
# 0x728366ed68565dc17cf6dd97330a859a6a56e87e2beef3bd828a4c4a54d8df06, 0x9e0477f9850dca41e42db0e4d154e3a098e5a000d995e421849fcd5df27882bd = HKDF(0xcc2c6e467efc8067720c2d09c139d1f77731893aad1defa14f9bf3c48d3f1d31, 0x3fbdc101abd1132ca3a0ae34a669d8d9ba69a587e0bb4ddd59524541cf4813d8)
output 1000: 0x4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09
output 1001: 0x2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36
2017-01-04 06:22:25 +01:00
2017-05-02 09:23:46 +02:00
# Acknowledgments
2016-11-15 02:23:20 +01:00
TODO(roasbeef); fin
# References
2017-02-23 09:38:15 +01:00
1. < a id = "reference-1" > https://tools.ietf.org/html/rfc7539</ a >
2. < a id = "reference-2" > http://noiseprotocol.org/noise.html</ a >
3. < a id = "reference-3" > https://tools.ietf.org/html/rfc5869</ a >
2016-11-15 02:23:20 +01:00
2016-11-30 21:05:50 +01:00
2016-11-15 02:23:20 +01:00
# Authors
FIXME
2016-11-22 20:52:59 +01:00
2017-05-11 03:46:05 +02:00
![Creative Commons License ](https://i.creativecommons.org/l/by/4.0/88x31.png "License CC-BY" )
< br >
2016-11-22 20:52:59 +01:00
This work is licensed under a [Creative Commons Attribution 4.0 International License ](http://creativecommons.org/licenses/by/4.0/ ).