Skip to content

Commit

Permalink
BOLT-04: convert blinded paths syntax to use LaTeX rendering
Browse files Browse the repository at this point in the history
Github now supports inline LaTeX rendering:
https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/writing-mathematical-expressions

In this commit, we use this new feature to improve the rendering of the
routines for blinded paths.
  • Loading branch information
Roasbeef committed Mar 28, 2024
1 parent 25e7dbd commit ed012ed
Showing 1 changed file with 30 additions and 30 deletions.
60 changes: 30 additions & 30 deletions 04-onion-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,58 +492,58 @@ may contain the following TLV fields:

#### Requirements

A recipient `N_r` creating a blinded route `N_0 -> N_1 -> ... -> N_r` to itself:
A recipient $`N_r`$ creating a blinded route $`N_0 \rightarrow N_1 \rightarrow ... \rightarrow N_r`$ to itself:

- MUST create a blinded node ID `B_i` for each node using the following algorithm:
- `e_0 <-$ {0;1}^256` (`e_0` SHOULD be obtained via CSPRG)
- `E_0 = e_0 * G`
- MUST create a blinded node ID $`B_i`$ for each node using the following algorithm:
- $`e_0 /leftarrow {0;1}^256`$ ($`e_0`$ SHOULD be obtained via CSPRG)
- $`E_0 = e_0 \cdot G`$
- For every node in the route:
- let `N_i = k_i * G` be the `node_id` (`k_i` is `N_i`'s private key)
- `ss_i = SHA256(e_i * N_i) = SHA256(k_i * E_i)` (ECDH shared secret known only by `N_r` and `N_i`)
- `B_i = HMAC256("blinded_node_id", ss_i) * N_i` (blinded `node_id` for `N_i`, private key known only by `N_i`)
- `rho_i = HMAC256("rho", ss_i)` (key used to encrypt the payload for `N_i` by `N_r`)
- `e_{i+1} = SHA256(E_i || ss_i) * e_i` (blinding ephemeral private key, only known by `N_r`)
- `E_{i+1} = SHA256(E_i || ss_i) * E_i` (NB: `N_i` MUST NOT learn `e_i`)
- MAY replace `E_{i+1}` with a different value, but if it does:
- MUST set `encrypted_data_tlv[i].next_blinding_override` to `E_{i+1}`
- let $`N_i = k_i * G`$ be the `node_id` ($`k_i`$ is $`N_i`$'s private key)
- $`ss_i = SHA256(e_i * N_i) = SHA256(k_i * E_i)$` (ECDH shared secret known only by $`N_r`$ and $`N_i`$)
- $`B_i = HMAC256(\text{"blinded\_node\_id"}, ss_i) * N_i`$ (blinded `node_id` for $`N_i`$, private key known only by $`N_i`$)
- $`rho_i = HMAC256(\text{"rho"}, ss_i)`$ (key used to encrypt the payload for $`N_i`$ by $`N_r`$)
- $`e_{i+1} = SHA256(E_i || ss_i) * e_i`$ (blinding ephemeral private key, only known by $`N_r`$)
- $`E_{i+1} = SHA256(E_i || ss_i) * E_i`$ (NB: $`N_i`$ MUST NOT learn $`e_i`$)
- MAY replace $`E_{i+1}`$ with a different value, but if it does:
- MUST set `encrypted_data_tlv[i].next_blinding_override` to `$E_{i+1}$`
- MAY store private data in `encrypted_data_tlv[r].path_id` to verify that the route is used in the right context and was created by them
- SHOULD add padding data to ensure all `encrypted_data_tlv[i]` have the same length
- MUST encrypt each `encrypted_data_tlv[i]` with ChaCha20-Poly1305 using the corresponding `rho_i` key and an all-zero nonce to produce `encrypted_recipient_data[i]`
- MUST communicate the blinded node IDs `B_i` and `encrypted_recipient_data[i]` to the sender
- MUST communicate the real node ID of the introduction point `N_0` to the sender
- MUST communicate the first blinding ephemeral key `E_0` to the sender
- MUST communicate the blinded node IDs $`B_i`$ and `encrypted_recipient_data[i]` to the sender
- MUST communicate the real node ID of the introduction point $`N_0`$ to the sender
- MUST communicate the first blinding ephemeral key $`E_0`$ to the sender

A reader:

- If it receives `blinding_point` (`E_i`) from the prior peer:
- MUST use `b_i` instead of its private key `k_i` to decrypt the onion.
- If it receives `blinding_point` ($`E_i`$) from the prior peer:
- MUST use $`b_i`$ instead of its private key $`k_i`$ to decrypt the onion.
Note that the node may instead tweak the onion ephemeral key with
`HMAC256("blinded_node_id", ss_i)` which achieves the same result.
$`HMAC256(\text{"blinded\_node\_id}", ss_i)`$ which achieves the same result.
- Otherwise:
- MUST use `k_i` to decrypt the onion, to extract `current_blinding_point` (`E_i`).
- MUST use $`k_i`$ to decrypt the onion, to extract `current_blinding_point` ($`E_i`$).
- MUST compute:
- `ss_i = SHA256(k_i * E_i)` (standard ECDH)
- `b_i = HMAC256("blinded_node_id", ss_i) * k_i`
- `rho_i = HMAC256("rho", ss_i)`
- `E_{i+1} = SHA256(E_i || ss_i) * E_i`
- MUST decrypt the `encrypted_data` field using `rho_i` and use the
- $`ss_i = SHA256(k_i * E_i)`$ (standard ECDH)
- $`b_i = HMAC256(\text{"blinded\_node\_id"}, ss_i) * k_i`$
- $`rho_i = HMAC256(\text{"rho"}, ss_i)`$
- $`E_{i+1} = SHA256(E_i || ss_i) * E_i`$
- MUST decrypt the `encrypted_data` field using $`rho_i`$ and use the
decrypted fields to locate the next node
- If the `encrypted_data` field is missing or cannot be decrypted:
- MUST return an error
- If `encrypted_data` contains a `next_blinding_override`:
- MUST use it as the next blinding point instead of `E_{i+1}`
- MUST use it as the next blinding point instead of $`E_{i+1}`$
- Otherwise:
- MUST use `E_{i+1}` as the next blinding point
- MUST use $`E_{i+1}`$ as the next blinding point
- MUST forward the onion and include the next blinding point in the lightning
message for the next node

The final recipient:

- MUST compute:
- `ss_r = SHA256(k_r * E_r)` (standard ECDH)
- `b_r = HMAC256("blinded_node_id", ss_r) * k_r`
- `rho_r = HMAC256("rho", ss_r)`
- MUST decrypt the `encrypted_data` field using `rho_r`
- $`ss_r = SHA256(k_r * E_r)`$ (standard ECDH)
- $`b_r = HMAC256(\text{"blinded\_node\_id"}, ss_r) * k_r`$
- $`rho_r = HMAC256(\text{"rho"}, ss_r)`$
- MUST decrypt the `encrypted_data` field using $`rho_r`$
- If the `encrypted_data` field is missing or cannot be decrypted:
- MUST return an error
- MUST ignore the message if the `path_id` does not match the blinded route it
Expand Down

0 comments on commit ed012ed

Please sign in to comment.