fix(noise): change message identification method; minor fixes

This commit is contained in:
s1fr0 2022-09-01 13:09:02 +02:00
parent 7b27e17f23
commit bd1e42b62f
No known key found for this signature in database
GPG Key ID: 2C041D60117BFF46
1 changed files with 36 additions and 35 deletions

View File

@ -21,13 +21,18 @@ If device `A` doesn't have a camera while device `B` does, [it is possible](#Rat
- `Curve25519`: the underlying elliptic curve for Diffie-Hellman (DH) operations. - `Curve25519`: the underlying elliptic curve for Diffie-Hellman (DH) operations.
### The `WakuPairing` Noise Handshake ### The `WakuPairing` Noise Handshake
The devices execute a custom handshake derived from `X1X1`, where they mutually exchange and authenticate their device static keys, i.e. The devices execute a custom handshake derived from `X1X1`, where they mutually exchange and authenticate their device static keys by exchanging messages over the content topic
```
contentTopic = /{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/proto
```
The handshake, detailed in next section, can be summarized as:
``` ```
WakuPairing: WakuPairing:
0. <- eB {H(sB||r), contentTopic} 0. <- eB {H(sB||r), contentTopicParams, messageNametag}
... ...
1. -> eA, eAeB {H(sA||s)} [auth_code] 1. -> eA, eAeB {H(sA||s)} [authcode]
2. <- sB, eAsB {r} 2. <- sB, eAsB {r}
3. -> sA, sAeB, sAsB {s} 3. -> sA, sAeB, sAsB {s}
@ -35,35 +40,37 @@ WakuPairing:
``` ```
Beside the ephemeral key, all the information embedded in the QR code should be passed to the prologue of the Noise handshake (e.g. `H(sB||r)`, `contentTopic`, etc.). Beside the ephemeral key, all the information embedded in the QR code should be passed to the prologue of the Noise handshake (e.g. `H(sB||r)`, `contentTopic`, `message_nametag`, etc.).
### Protocol Flow ### Protocol Flow
1. The device `B` exposes through a QR code a Base64 serialization of: 1. The device `B` exposes through a QR code a Base64 serialization of:
- An ephemeral public key `eB`; - An ephemeral public key `eB`;
- A `contentTopic` where the information exchange will take place. `contentTopic` follows [23/WAKU2-TOPICS](https://rfc.vac.dev/spec/23/#content-topics) specifications and is then of the form `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/{random-message-id}/proto` for a randomly generated `random-message-id`. `contentTopic` can be then serialized in compressed form as `{application-name}:{application-version}:{shard-id}:{random-message-id}`. - The content topic parameters `contentTopicParams = {application-name}, {application-version}, {shard-id}`.
- A randomly generated 8-bytes long `messageNametag`.
- A commitment `H(sB||r)` for its static key `sB` where `r` is a random fixed-lenght value. - A commitment `H(sB||r)` for its static key `sB` where `r` is a random fixed-lenght value.
2. The device `A`: 2. The device `A`:
- scans the QR code; - scans the QR code;
- obtains `eB`, `contentTopic`, `Hash(sB|r)`; - obtains `eB`, `contentTopicParams`, `messageNametag`, `Hash(sB|r)`;
- initializes the Noise handshake by passing `contentTopic` and `Hash(sB||r)` to the handshake prologue; - checks if `{application-name}` and `{application-version}` from `contentTopicParams` match the local application name and version: if not, aborts the pairing.
- initializes the Noise handshake by passing `contentTopicParams`, `messageNametag` and `Hash(sB||r)` to the handshake prologue;
- executes the pre-handshake message, i.e. processes the key `eB`; - executes the pre-handshake message, i.e. processes the key `eB`;
- executes the first handshake message over `contentTopic`, i.e. - executes the first handshake message over `contentTopic`, i.e.
- processes and sends a Waku message containing an ephemeral key `eA`; - processes and sends a Waku message containing an ephemeral key `eA`;
- performs `DH(eA,eB)` (which computes a symmetric encryption key); - performs `DH(eA,eB)` (which computes a symmetric encryption key);
- attach as payload to the handshake message a commitment `H(sA|s)` for `A`'s static key `sA`, where `s` is a random fixed-lenght value; - attach as payload to the handshake message a commitment `H(sA|s)` for `A`'s static key `sA`, where `s` is a random fixed-lenght value;
- an 8-digits authorization code `auth_code` obtained as `HKDF(h) mod 10^8` is displayed on the device, where `h`is the handshake value obtained once the first handshake message is processed. - an 8-digits authorization code `authcode` obtained as `HKDF(h) mod 10^8` is displayed on the device, where `h`is the handshake value obtained once the first handshake message is processed.
3. The device `B`: 3. The device `B`:
- listens to any message sent to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/*` and locally filters only messages sent to `contentTopic`. If any, continues. - listens to messages sent to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/proto` and locally filters only those with [Waku payload](https://rfc.vac.dev/spec/35/#abnf) starting with `messageNametag`. If any, continues.
- initializes the Noise handshake by passing `contentTopic` and `Hash(sB||r)` to the handshake prologue; - initializes the Noise handshake by passing `contentTopicParams`, `messageNametag` and `Hash(sB||r)` to the handshake prologue;
- executes the pre-handshake message, i.e. processes its static key `eB`; - executes the pre-handshake message, i.e. processes its static key `eB`;
- executes the first handshake message, i.e. - executes the first handshake message, i.e.
- obtains from the received message a public key `eA`. If `eA` is not a valid public key, the protocol is aborted. - obtains from the received message a public key `eA`. If `eA` is not a valid public key, the protocol is aborted.
- performs `DH(eA,eB)` (which computes a symmetric encryption key); - performs `DH(eA,eB)` (which computes a symmetric encryption key);
- decrypts the commitment `H(sA||s)` for `A`'s static key `sA`. - decrypts the commitment `H(sA||s)` for `A`'s static key `sA`.
- an 8-digits authorization code `auth_code` obtained as `HKDF(h) mod 10^8` is displayed on the device, where `h`is the handshake value obtained once the first handshake message is processed. - an 8-digits authorization code `authcode` obtained as `HKDF(h) mod 10^8` is displayed on the device, where `h`is the handshake value obtained once the first handshake message is processed.
4. Device `A` and `B` wait the user to confirm with an interaction (button press) that the authorization code displayed on both devices are the same. If not, the protocol is aborted. 4. Device `A` and `B` wait the user to confirm with an interaction (button press) that the authorization code displayed on both devices are the same. If not, the protocol is aborted.
@ -74,7 +81,7 @@ Beside the ephemeral key, all the information embedded in the QR code should be
- attaches as payload the (encrypted) commitment randomness `r` used to compute `H(sB||r)`. - attaches as payload the (encrypted) commitment randomness `r` used to compute `H(sB||r)`.
6. The device `A`: 6. The device `A`:
- listens to any message sent to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/*` and locally filters only messages sent to `contentTopic`. If any, continues. - listens to messages sent to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/proto` and locally filters only those with Waku payload starting with `messageNametag`. If any, continues.
- obtains from decrypting the received message a public key `sB`. If `sB` is not a valid public key, the protocol is aborted. - obtains from decrypting the received message a public key `sB`. If `sB` is not a valid public key, the protocol is aborted.
- performs `DH(eA,sB)` (which updates a symmetric encryption key); - performs `DH(eA,sB)` (which updates a symmetric encryption key);
- decrypts the payload to obtain the randomness `r`. - decrypts the payload to obtain the randomness `r`.
@ -89,7 +96,7 @@ Beside the ephemeral key, all the information embedded in the QR code should be
7. The device `B`: 7. The device `B`:
- locally filters new messages addressed to `contentTopic`. If any, continues. - listens to messages sent to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/proto` and locally filters only those with Waku payload starting with `messageNametag`. If any, continues.
- obtains from decrypting the received message a public key `sA`. If `sA` is not a valid public key, the protocol is aborted. - obtains from decrypting the received message a public key `sA`. If `sA` is not a valid public key, the protocol is aborted.
- performs `DH(sA,eB)` (which updates a symmetric encryption key); - performs `DH(sA,eB)` (which updates a symmetric encryption key);
- performs `DH(sA,sB)` (which updates a symmetric encryption key); - performs `DH(sA,sB)` (which updates a symmetric encryption key);
@ -107,16 +114,16 @@ This allows pairing in case device `A` does not have a camera to scan a QR (e.g.
The resulting handshake would then be: The resulting handshake would then be:
``` ```
WakuPairing2: WakuPairing2:
0. -> eA {H(sA||s), contentTopic} 0. -> eA {H(sB||r), contentTopicParams, messageNametag}
... ...
1. <- eB, eAeB {H(sB||r)} [auth_code] 1. <- eB, eAeB {H(sB||r)} [authcode]
2. <- sB, eAsB {r} 2. <- sB, eAsB {r}
3. -> sA, sAeB, sAsB {s} 3. -> sA, sAeB, sAsB {s}
{}: payload, []: user interaction {}: payload, []: user interaction
``` ```
## Security Analysis (sketch) ## Security Analysis
### Assumptions ### Assumptions
- The attacker is active, i.e. can interact with both devices `A` and `B` by sending messages over `contentTopic`. - The attacker is active, i.e. can interact with both devices `A` and `B` by sending messages over `contentTopic`.
@ -148,16 +155,13 @@ WakuPairing2:
- by being the pairing requester, it cannot probe device `A` identity without revealing its own (static key) first. Note that device `B` static key and its commitment can be binded to other cryptographic material (e.g., seed phrase). - by being the pairing requester, it cannot probe device `A` identity without revealing its own (static key) first. Note that device `B` static key and its commitment can be binded to other cryptographic material (e.g., seed phrase).
- Device `B` opens a commitment to its static key at message `2.` because: - Device `B` opens a commitment to its static key at message `2.` because:
- if device `A` replies concluding the handshake according to the protocol, device `B` acknowledges that device `A` correctly received his static key `sB`, since `r` was encrypted under an encryption key derived from the static key `sB` and the genuine (due to the previous `auth_code` verification) ephemeral keys `eA` and `eB`. - if device `A` replies concluding the handshake according to the protocol, device `B` acknowledges that device `A` correctly received his static key `sB`, since `r` was encrypted under an encryption key derived from the static key `sB` and the genuine (due to the previous `authcode` verification) ephemeral keys `eA` and `eB`.
- Device `A` opens a commitment to its static key at message `3.` because: - Device `A` opens a commitment to its static key at message `3.` because:
- if device `B` doesn't abort the pairing, device `A` acknowledges that device `B` correctly received his static key `sA`, since `s` was encrypted under an encryption key derived from the static keys `sA` and `sB` and the genuine (due to the previous `auth_code` verification) ephemeral keys `eA` and `eB`. - if device `B` doesn't abort the pairing, device `A` acknowledges that device `B` correctly received his static key `sA`, since `s` was encrypted under an encryption key derived from the static keys `sA` and `sB` and the genuine (due to the previous `authcode` verification) ephemeral keys `eA` and `eB`.
- Device `A` and `B` listens to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/*` and not to `contentTopic` because:
- in this way they don't leak to store nodes their interest for encrypted messages sent to `contentTopic`.
# Secure Transfer (sketch) # Secure Transfer
Once the handshake is concluded, sensitive information can be exchanged using the encryption keys agreed during the pairing phase. If stronger security guarantees are required, some [additional tweaks](#Additional-Possible-Tweaks) are possible. Once the handshake is concluded, sensitive information can be exchanged using the encryption keys agreed during the pairing phase. If stronger security guarantees are required, some [additional tweaks](#Additional-Possible-Tweaks) are possible.
@ -208,27 +212,24 @@ TransferPhase:
{}: payload {}: payload
``` ```
## Content Topic Derivation ## Messages Nametag Derivation
To reduce metadata leakages and increase devices's anonymity over the p2p network, [35/WAKU2-NOISE](https://rfc.vac.dev/spec/37/#session-states) suggests to use some common secrets `ctsInbound, ctsOutbound` (e.g. `ctsInbound, ctsOutbound = HKDF(h)` where `h` is the handshake hash value of the Handshake State at some point of the pairing phase) in order to frequently and deterministically change `contentTopic` of messages exchanged during the pairing and transfer phase - ideally, at each message or round trip communication. To reduce metadata leakages and increase devices's anonymity over the p2p network, [35/WAKU2-NOISE](https://rfc.vac.dev/spec/37/#session-states) suggests to use some common secrets `ctsInbound, ctsOutbound` (e.g. `ctsInbound, ctsOutbound = HKDF(h)` where `h` is the handshake hash value of the Handshake State at some point of the pairing phase) in order to frequently and deterministically change the `messageNametag` of messages exchanged during the pairing and transfer phase - ideally, at each message exchanged.
Given the proposed content topic format Given the proposed construction,
``` the `ctsInbound` and `ctsOutbound` secrets can be used to iteratively generate the `messageNametag` field of Waku payloads for inbound and outbound messages, respectively.
/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/{random-message-id}/proto
```
the `ctsInbound` and `ctsOutbound` secrets can be used to iteratively generate the `{random-message-id}` field of content topics for inbound and outbound messages, respectively.
The derivation of `{random-message-id}` should be deterministic only for communicating devices and independent from message content, otherwise lost messages will prevent computing the next content topic. A possible approach consists in computing the `n`-th `{random-message-id}` as `H( ctsInbound || n)`, where `n` is serialized as `uint64`. The derivation of `messageNametag` should be deterministic only for communicating devices and independent from message content, otherwise lost messages will prevent computing the next message nametag. A possible approach consists in computing the `n`-th `messageNametag` as `H( ctsInbound || n)`, where `n` is serialized as `uint64`.
In this way, sender's and recipient's devices can keep updated a buffer of `random-message-id` to sieve while listening to `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/*` (i.e., the next 50 not yet seen), and become then able to further identify if one or more messages were eventually lost/not-yet-delivered during the communication. In this way, sender's and recipient's devices can keep updated a buffer of `messageNametag` to sieve while listening to messages sent over `/{application-name}/{application-version}/wakunoise/1/sessions-{shard-id}/` (i.e., the next 50 not yet seen), and become then able to further identify if one or more messages were eventually lost/not-yet-delivered during the communication.
This approach brings also the advantage that communicating devices can efficiently identify encrypted messages addressed to them. This approach brings also the advantage that communicating devices can efficiently identify encrypted messages addressed to them.
We note that since the `ChaChaPoly` cipher used to encrypt messages supports *additional data*, an encrypted payload can be further authenticated by passing the `contentTopic` as additional data to the encryption/decryption routine. In this way, an attacker would be unable to craft an authenticated Waku message sent to a content topic agreed during the pairing phase. We note that since the `ChaChaPoly` cipher used to encrypt messages supports *additional data*, an encrypted payload can be further authenticated by passing the `messageNametag` as additional data to the encryption/decryption routine. In this way, an attacker would be unable to craft an authenticated Waku message even in case the currently used symmetric encryption key is compromised, unless `ctsInbound`, `ctsOutbound` or the `messageNametag` buffer lists were compromised too.
# Future work: n-to-1 pairing # Future Work: `n-to-1` Device Pairing
The above protocol pairs a single device `A` with `B`, creating the conditions for a secure transfer. However, we would like to efficiently address scenarios (e.g. the [NM](https://rfc.vac.dev/spec/37/#the-nm-session-management-mechanism) session management mechanism) where a device `B` is paired with multiple devices `A1, A2, ..., An`, which were, in turn, already paired two-by-two. A naive approach requires `B` to be paired with each of such devices, but exposing/scanning `n` QRs is clearly impractical for a large number of devices. The above protocol pairs a single device `A` with `B`, creating the conditions for a secure transfer. However, we would like to efficiently address scenarios (e.g. the [NM](https://rfc.vac.dev/spec/37/#the-nm-session-management-mechanism) session management mechanism) where a device `B` is paired with multiple devices `A1, A2, ..., An`, which were, in turn, already paired two-by-two. A naive approach requires `B` to be paired with each of such devices, but exposing/scanning `n` QRs would quickly become impractical as the number of devices increases.
As a future work we wish to design a n-to-1 pairing protocol, where only one out of `n` devices scans the QR exposed by the pairing requester device and the latter can efficiently (in term of exchanged messages) be securely paired to all of them. As a future work, we wish to design a `n-to-1` pairing protocol, where only one out of `n` devices scans the QR exposed by the pairing requester device and the latter can efficiently (in term of exchanged messages) be securely paired to all of them.
A possible approach requires that all already paired devices share a list of *pairing key bundles*, that device `B` can securely receive from the device it has been paired with and use to complete multiple pairings, in a similarly fashion as X3DH. A possible approach requires that all already paired devices share a list of *pairing key bundles*, that device `B` can securely receive from the device it has been paired with and use to complete multiple pairings, in a similarly fashion as X3DH.