This specification describes how payloads of [Waku messages](https://github.com/vacp2p/rfc-index/tree/main/waku/standards/core/14) with [version 2](https://github.com/vacp2p/rfc-index/tree/main/waku/standards/core/14) can be encrypted
This specification extends the functionalities provided by [26/WAKU-PAYLOAD](https://github.com/vacp2p/rfc-index/blob/main/waku/standards/application/26/payload.md),
Specifically, it adds support to the [`ChaChaPoly`](https://www.ietf.org/rfc/rfc7539.txt) cipher for symmetric authenticated encryption.
It further describes how the [Noise Protocol Framework](http://www.noiseprotocol.org/noise.html) can be used to exchange cryptographic keys and encrypt/decrypt messages
in a way that the latter are authenticated and protected by _strong forward secrecy_.
- _Confidentiality_: the adversary should not be able to learn what data is being sent from one Waku endpoint to one or several other Waku endpoints. - _Strong forward secrecy_: an active adversary cannot decrypt messages nor infer any information on the employed encryption key,
even in the case he has access to communicating parties' long-term private keys (during or after their communication).
- _Authenticity_: the adversary should not be able to cause a Waku endpoint to accept messages coming from an endpoint different than their original senders.
- _Integrity_: the adversary should not be able to cause a Waku endpoint to accept data that has been tampered with.
- _Identity-hiding_: once a secure communication channel is established,
a passive adversary should not be able to link exchanged encrypted messages to their corresponding sender and recipient.
Two parties executing a Noise protocol exchange one or more [_handshake messages_](http://www.noiseprotocol.org/noise.html#message-format) and/or [_transport messages_](http://www.noiseprotocol.org/noise.html#message-format).
A Noise protocol consists of one or more Noise handshakes.
During a Noise handshake, two parties exchange multiple handshake messages.
A handshake message contains _ephemeral keys_ and/or _static keys_ from one of the parties
and an encrypted or unencrypted payload that can be used to transmit optional data.
These public keys are used to perform a protocol-dependent sequence of Diffie-Hellman operations,
whose results are all hashed into a shared secret key.
After a handshake is complete, each party will then use the derived shared secret key to send and receive authenticated encrypted transport messages.
We refer to [Noise protocol framework specifications](http://www.noiseprotocol.org/noise.html#processing-rules) for the full details on how parties shared secret key is derived from each exchanged message.
Four Noise handshakes are currently supported: `K1K1`, `XK1`, `XX`, `XXpsk0`. Their description can be found in [Appendix: Supported Handshakes Description](#Appendix-Supported-Handshake-Description).
- [`Curve25519`](http://www.noiseprotocol.org/noise.html#the-25519-dh-functions) for Diffie-Hellman key-exchanges (32 bytes curve coordinates);
- [`ChaChaPoly`](http://www.noiseprotocol.org/noise.html#the-chachapoly-cipher-functions) for symmetric authenticated encryption (16 bytes authentication tag);
- [`SHA256`](http://www.noiseprotocol.org/noise.html#the-sha256-hash-function) hash function used in [`HMAC`](http://www.noiseprotocol.org/noise.html#hash-functions) and [`HKDF`](http://www.noiseprotocol.org/noise.html#hash-functions) keys derivation chains (32 bytes output size);
#### Content Topics and Message Nametags of Noise Handshake Messages
We note that all [design requirements](#Design-requirements) on exchanged messages would be satisfied only _after_ a supported Noise handshake is completed,
corresponding to a total of 1 Round Trip Time communication _(1-RTT)_.
In particular, identity-hiding properties can be guaranteed only if the recommendation described in [After-handshake](#After-handshake) are implemented.
In the following, we assume that communicating parties reciprocally know an initial [`contentTopic`](https://github.com/vacp2p/rfc-index/tree/main/waku/standards/core/14/#wakumessage)
The second handshake message MAY be sent/received with a `message-nametag` deterministically derived from the handshake state obtained after processing the first handshake message
After the second handshake message is correctly received by initiators, the recommendation described in [After-handshake](#After-handshake) SHOULD be implemented to provide full identity-hiding guarantees for both initiator and recipient against passive attackers.
-`message-nametag`: an arbitrary identifier for the Waku message (16 byte).
If the underlying encryption primitive supports it, the contents of this field SHOULD be passed as additional data to the encryption and decryption routines.
-`protocol-id`: identifies the protocol or primitive in use (1 byte).
-`0`: payload encodes an [after-handshake](#After-handshake) message.
-`handshake-message-len` MAY be 0;
-`transport-message` contains the Noise transport message;
-`10`,`11`,`12`,`13`: payload encodes a supported Noise handshake message.
-`transport-message` contains the Noise transport message;
-`30`: payload encapsulate a `ChaChaPoly` ciphertext `ct`.
-`handshake-message-len` is set to `0`;
-`transport-message` contains the concatenation of the encryption nonce (12 bytes) followed by the ciphertext `ct` and the authentication data for `ct` (16 bytes);
-`transport-message-len` is set accordingly to `transport-message` length;
encrypted transport messages SHOULD be padded before encryption.
It is therefore recommended to right pad transport messages using [RFC2630](https://datatracker.ietf.org/doc/html/rfc2630#section-6.3) so that their final length is a multiple of 248 bytes.
It is possible to have backward compatibility to symmetric/asymmetric encryption primitives from [26/WAKU-PAYLOAD](https://github.com/vacp2p/rfc-index/blob/main/waku/standards/application/26/payload.md),
effectively encapsulating payload encryption [14/WAKU-MESSAGE version 1](https://github.com/vacp2p/rfc-index/tree/main/waku/standards/core/14/#version1) in [version 2](https://github.com/vacp2p/rfc-index/tree/main/waku/standards/core/14/#version2).
and set the `transport-message` field to the [26/WAKU-PAYLOAD](https://github.com/vacp2p/rfc-index/blob/main/waku/standards/application/26/payload.md) `data` field, whenever these `protocol-id` values are set.
-`transport-message`: contains the [26/WAKU-PAYLOAD](https://github.com/vacp2p/rfc-index/blob/main/waku/standards/application/26/payload.md) `data` field (AES-256-GCM or ECIES, depending on `protocol-id`);
it SHOULD be decoded as the `data` field in [26/WAKU-PAYLOAD](https://github.com/vacp2p/rfc-index/blob/main/waku/standards/application/26/payload.md) specification.
Supported Noise handshakes address four typical scenarios occurring when an encrypted communication channel between Alice and Bob is going to be created:
- Alice and Bob share no key material and they don't know each others' static key.
- Alice and Bob share some key material, but they don't know each others' static key.
**Adversarial Model**: an active attacker who compromised one party's static key may lower the identity-hiding security guarantees provided by some handshakes. In our security model we exclude such adversary, but for completeness we report a summary of possible de-anonymization attacks that can be performed by an active attacker.
If Alice and Bob know each others' static key (e.g., these are public or were already exchanged in a previous handshake) , they MAY execute a `K1K1` handshake. Using [Noise notation](https://noiseprotocol.org/noise.html#overview-of-handshake-state-machine) _(Alice is on the left)_ this can be sketched as:
We note that here only ephemeral keys are exchanged. This handshake is useful in case Alice needs to instantiate a new separate encrypted communication channel with Bob, e.g. opening multiple parallel connections, file transfers, etc.
**Security considerations on identity-hiding (active attacker)**: no static key is transmitted, but an active attacker impersonating Alice can check candidates for Bob's static key.
### The `XK1` Handshake
Here, Alice knows how to initiate a communication with Bob and she knows his public static key: such discovery can be achieved, for example, through a publicly accessible register of users' static keys, smart contracts, or through a previous public/private advertisement of Bob's static key.
A Noise handshake pattern that suits this scenario is `XK1`:
```
XK1:
<-s
...
-> e
<-e,ee,es
-> s, se
```
Within this handshake, Alice and Bob reciprocally authenticate their static keys `s` using ephemeral keys `e`. We note that while Bob's static key is assumed to be known to Alice (and hence is not transmitted), Alice's static key is sent to Bob encrypted with a key derived from both parties ephemeral keys and Bob's static key.
**Security considerations on identity-hiding (active attacker)**: Alice's static key is encrypted with forward secrecy to an authenticated party. An active attacker initiating the handshake can check candidates for Bob's static key against recorded/accepted exchanged handshake messages.
If Alice is not aware of any static key belonging to Bob (and neither Bob knows anything about Alice), she can execute an `XX` handshake, where each party tran**X**mits to the other its own static key.
We note that the main difference with `XK1` is that in second step Bob sends to Alice his own static key encrypted with a key obtained from an ephemeral-ephemeral Diffie-Hellman exchange.
This handshake can be slightly changed in case both Alice and Bob pre-shares some secret `psk` which can be used to strengthen their mutual authentication during the handshake execution. One of the resulting protocol, called `XXpsk0`, goes as follow:
**Security considerations on identity-hiding (active attacker)**: Alice's static key is encrypted with forward secrecy to an authenticated party for both `XX` and `XXpsk0` handshakes. In `XX`, Bob's static key is encrypted with forward secrecy but is transmitted to a non-authenticated user which can then be an active attacker. In `XXpsk0`, instead, Bob's secret key is protected by forward secrecy to a partially authenticated party (through the pre-shared secret `psk` but not through any static key), provided that `psk` was not previously compromised (in such case identity-hiding properties provided by the `XX` handshake applies).