Skip to content

Commit d22b4e6

Browse files
committed
Route Blinding
Route blinding allows a recipient to provide a blinded route to potential payers. Each node_id in the route is tweaked, and dummy hops may be included. This is an alternative to rendezvous to preserve recipient anonymity. It has a different set of trade-offs: onions are re-usable, but the privacy guarantees are a bit weaker and require more work (e.g. when handling errors).
1 parent 61dd63a commit d22b4e6

1 file changed

Lines changed: 296 additions & 0 deletions

File tree

proposals/route-blinding.md

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# Route Blinding
2+
3+
## Table of Contents
4+
5+
* [Proposal](#proposal)
6+
* [Introduction](#introduction)
7+
* [Overview](#overview)
8+
* [Notations](#notations)
9+
* [Requirements](#requirements)
10+
* [Encrypted recipient data](#encrypted-recipient-data)
11+
* [Creating a blinded route](#creating-a-blinded-route)
12+
* [Sending to a blinded route](#sending-to-a-blinded-route)
13+
* [Receiving from a blinded route](#receiving-from-a-blinded-route)
14+
* [Sample flow](#sample-flow)
15+
* [Unblinding channels via fee probing](#unblinding-channels-via-fee-probing)
16+
* [Tips and Tricks](#tips-and-tricks)
17+
* [Recipient pays fees](#recipient-pays-fees)
18+
* [Dummy hops](#dummy-hops)
19+
* [Wallets and unannounced channels](#wallets-and-unannounced-channels)
20+
* [Blinded trampoline route](#blinded-trampoline-route)
21+
* [FAQ](#faq)
22+
* [Why not use rendezvous](#why-not-use-rendezvous)
23+
* [Why not use HORNET](#why-not-use-hornet)
24+
25+
## Proposal
26+
27+
### Introduction
28+
29+
Route blinding is a lightweight technique to provide recipient anonymity by blinding an arbitrary
30+
amount of hops at the end of an onion path. It's more flexible than rendezvous because it lets
31+
senders arbitrarily update amounts and lock times, and reuse a blinded route multiple times (which
32+
is useful when retrying a failed route or using multi-part payments).
33+
34+
The downside compared to rendezvous is that senders have more leeway to probe by changing various
35+
variables, so the scheme needs to explicitly defend against probing attacks and may be less private.
36+
37+
Some use-cases where route blinding is useful include:
38+
39+
* Recipient anonymity when receiving payments
40+
* Using unannounced channels in invoices without revealing them
41+
* Forcing a payment to go through a specific set of intermediaries that can witness the payment
42+
* Providing anonymous reply paths for onion messages (offers, stuckless payments, etc)
43+
44+
### Overview
45+
46+
At a high level, route blinding works by having the recipient choose an introduction point and a
47+
route to himself from that introduction point. The recipient then blinds each node and channel
48+
along that route with ECDH. The recipient includes the blinded route and a secret in the invoice,
49+
which allows each node in the blinded route to incrementally unblind the payloads.
50+
51+
This scheme requires all the nodes in the blinded route and the sender to activate support for the
52+
feature. It only becomes effective once a big enough share of the network supports it.
53+
54+
### Notations
55+
56+
* A node `N(i)`'s `node_id` is defined as: `P(i) = k(i) * G`.
57+
* Blinded `node_id`s are defined as: `B(i) = b(i) * G`.
58+
* Ephemeral public keys are defined as: `E(i) = e(i) * G`.
59+
60+
### Requirements
61+
62+
A node `N(r)` wants to provide a blinded route `N(r) <- ... <- N(1) <- N(0)` that must be used
63+
to receive onion messages.
64+
65+
* The channels used along that route may be either announced or unannounced.
66+
* When used for payments, intermediate nodes in the blinded route MUST NOT learn `payment_secret`.
67+
* Intermediate nodes in the blinded route MUST NOT learn the `node_id` or `scid` of other
68+
intermediate nodes except for their immediate predecessor or successor.
69+
* Intermediate nodes in the blinded route MUST NOT learn their distance to the recipient `N(r)`.
70+
* Senders MUST NOT learn the real `node_id`s and `scid`s of the blinded intermediate hops after the
71+
introduction point `N(0)`.
72+
* If `N(r)` creates multiple blinded routes to herself, senders MUST NOT be able to tell that these
73+
routes lead to the same recipient (unless this information is leaked by higher layers of the
74+
protocol, such as using the same `payment_hash`).
75+
76+
### Encrypted recipient data
77+
78+
Route blinding introduces a new TLV field to the onion `tlv_payload`: the `encrypted_recipient_data`.
79+
80+
This field is used to carry data coming from the final recipient that cannot be modified by the
81+
sender. For route blinding it only needs to contain the `scid` to use when forwarding the message,
82+
but it may be extended with additional data in the future. It uses ChaCha20-Poly1305 as AEAD scheme.
83+
84+
1. type: 10 (`encrypted_recipient_data`)
85+
2. data:
86+
* [`...*byte`:`encrypted_recipient_data`]
87+
88+
Once decrypted, the content of this encrypted payload is a TLV stream that may contain any tlv
89+
record defined in Bolt 4 (onion TLV namespace).
90+
91+
### Creating a blinded route
92+
93+
`N(r)` performs the following steps to create a blinded route:
94+
95+
```text
96+
Initialization:
97+
98+
e(0) <- {0;1}^256
99+
E(0) = e(0) * G
100+
101+
Blinding:
102+
103+
For i = 0 to r-1:
104+
ss(i) = H(e(i) * P(i)) = H(k(i) * E(i)) // shared secret known only by N(r) and N(i)
105+
B(i) = HMAC256("blinded_node_id", ss(i)) * P(i) // Blinded node_id for N(i), private key known only by N(i)
106+
rho(i) = HMAC256("rho", ss(i)) // Key used to encrypt payload for N(i) by N(r)
107+
e(i+1) = H(E(i) || ss(i)) * e(i) // Ephemeral private key, only known by N(r)
108+
E(i+1) = H(E(i) || ss(i)) * E(i) // NB: N(i) must not learn e(i)
109+
110+
Blinded route:
111+
112+
(P(0),fees(0),cltv(0),encrypted_recipient_data(0))
113+
(B(1),fees(1),cltv(1),encrypted_recipient_data(1))
114+
...
115+
(B(r-1),fees(r-1),cltv(r-1),encrypted_recipient_data(r-1))
116+
```
117+
118+
Note that this is exactly the same construction as Sphinx, but at each hop we use the shared secret
119+
to derive a blinded `node_id` for `N(i)` for which the private key will only be known by `N(i)`.
120+
121+
The recipient needs to provide `E(0)` and the blinded route to potential senders.
122+
The `encrypted_recipient_data(i)` is encrypted with ChaCha20-Poly1305 using the `rho(i)` key, and
123+
contains the real `short_channel_id` to forward to (and potentially other fields).
124+
`E(i)` is included as additional authenticated data to detect probing attempts by the sender.
125+
126+
Note that the introduction point uses the real `node_id`, not the blinded one, because the sender
127+
needs to be able to locate this introduction point and find a route to it. But the sender will send
128+
`E(0)`, which will allow the introduction point to compute the shared secret and correctly forward.
129+
130+
Note that in the specific case of payments, the recipient can sign the invoice with `e(0)`.
131+
The sender will recover `E(0)` from the signature so no extra field needs to be added to Bolt 11.
132+
And this ensures the recipient doesn't reveal his real `node_id` through the invoice signature.
133+
134+
However, if the recipient wants to be able to prove invoice ownership in the future, she should
135+
sign the invoice with a different key and provide `E(0)` via a dedicated Bolt 11 field.
136+
137+
### Sending to a blinded route
138+
139+
The sender finds a route to the introduction point `N(0)`, and extends it with the blinded route.
140+
It then creates an onion for that route, and includes `E(0)` and `encrypted_recipient_data(0)` in
141+
the onion payload for `N(0)`.
142+
143+
When `N(0)` receives the onion and decrypts it, it finds `E(0)` in the payload and is able to
144+
compute the following:
145+
146+
```text
147+
ss(0) = H(k(0) * E(0))
148+
rho(0) = HMAC256("rho", ss(0))
149+
E(1) = H(E(0) || ss(0)) * E(0)
150+
```
151+
152+
It uses `rho(0)` to decrypt the `encrypted_recipient_data(0)` and discover the `scid` to forward to.
153+
It forwards the onion to the next node and includes `E(1)` in a TLV field in the message extension.
154+
155+
All the following intermediate nodes `N(i)` do the following steps:
156+
157+
```text
158+
E(i) <- extracted from TLV extension
159+
ss(i) = H(k(i) * E(i))
160+
b(i) = HMAC256("blinded_node_id", ss(i)) * k(i)
161+
Use b(i) to decrypt the incoming onion
162+
rho(i) = HMAC256("rho", ss(i))
163+
Use rho(i) to decrypt the `encrypted_recipient_data` inside the onion and discover the next node
164+
E(i+1) = H(E(i) || ss(i)) * E(i)
165+
Forward the onion to the next node and include E(i+1) in a TLV field in the message extension
166+
```
167+
168+
### Receiving from a blinded route
169+
170+
When `N(r)` receives the onion message and `E(r)` in the TLV extension, she does the same
171+
unwrapping as intermediate nodes. The difference is that the onion will be a final onion.
172+
173+
### Sample flow
174+
175+
Alice creates an invoice with the following blinded path: `Carol -> Bob -> Alice`.
176+
This invoice contains the following blinded path:
177+
178+
```text
179+
(P(carol),fees(carol),cltv(carol),encrypted_recipient_data(carol))
180+
(B(bob),fees(bob),cltv(bob),encrypted_recipient_data(bob))
181+
```
182+
183+
Eve can reach Carol via Dave: `Eve -> Dave -> Carol`.
184+
185+
```text
186+
Eve Dave Carol Bob Alice
187+
| | | | |
188+
| update_add_htlc | update_add_htlc | update_add_htlc | update_add_htlc |
189+
| +-------------------------------+ | +-------------------------------+ | +-------------------------------+ | +-------------------------------+ |
190+
| | amount: 10025 msat | | | amount: 10020 msat | | | amount: 10010 msat | | | amount: 10000 msat | |
191+
| | expiry: 125 | | | expiry: 120 | | | expiry: 110 | | | expiry: 100 | |
192+
| | onion_routing_packet: | | | onion_routing_packet: | | | onion_routing_packet: | | | onion_routing_packet: | |
193+
| | +---------------------------+ | | | +---------------------------+ | | | +---------------------------+ | | | +---------------------------+ | |
194+
| --> | | amount_fwd: 10020 msat | | --> | --> | | amount_fwd: 10010 msat | | --> | --> | | amount_fwd: 10000 msat | | --> | --> | | amount_fwd: 10000 msat | | --> |
195+
| | | expiry: 120 | | | | | expiry: 110 | | | | | expiry: 100 | | | | | expiry: 100 | | |
196+
| | | scid: scid_dc | | | | | encrd: encrypted(scid_cb) | | | | | encrd: encrypted(scid_ba) | | | | +---------------------------+ | |
197+
| | +---------------------------+ | | | | eph_key: E(carol) | | | | +---------------------------+ | | | tlv_extension | |
198+
| +-------------------------------+ | | +---------------------------+ | | | tlv_extension | | | +-------------------+ | |
199+
| | +-------------------------------+ | | +-------------------+ | | | | eph_key: E(alice) | | |
200+
| | | | | eph_key: E(bob) | | | | +-------------------+ | |
201+
| | | | +-------------------+ | | +-------------------------------+ |
202+
| | | +-------------------------------+ | |
203+
```
204+
205+
NB: the `encrypted_recipient_data` is annotated `encrd` for brevity.
206+
207+
### Unblinding channels via fee probing
208+
209+
The fees and cltv for the blinded route can be abused by the sender to try to unblind the real
210+
nodes and channels used. The sender can create onions with increased fees/cltv for the first
211+
blinded hop, starting with very low values. While the fee/cltv is below the real fee of the first
212+
hop, the sender will get an error from `N(0)`. Once the fee/cltv proposed actually satisfies the
213+
first hop's requirements, the error will come from another node `N(i)` inside the blinded path.
214+
215+
The sender can then unblind channels one-by-one by discovering their real fees/cltv and matching
216+
those to existing channels in the graph.
217+
218+
To mitigate this, when nodes along the blinded path are offered an invalid HTLC, they should:
219+
220+
* return a dummy error encrypted with a throw-away key: the sender will receive an error she can't
221+
decrypt and doesn't know which node generated it
222+
* hold the HTLC for a random amount of time before sending the error (otherwise the sender can
223+
still use timing to guess which node errored out)
224+
225+
Even with such mitigations the sender can discover the real fees/cltv of one of the blinded
226+
channels. To do so she uses the correct fees and cltv for all but one channel, and for that target
227+
channel she tries fees/cltv until the payment succeeds. Once the payment succeeds she knows the
228+
approximate fees/cltv of the target channel (but since the payment succeeded, she can't continue
229+
probing).
230+
231+
Maybe nodes along the blinded path could use slightly different fees/cltv than what they publicly
232+
advertize? Or the recipient could add some fuzzing to it to blind them more?
233+
234+
Are those mitigations enough? Or can a clever attacker still work around them?
235+
236+
## Tips and Tricks
237+
238+
### Recipient pays fees
239+
240+
It may be unfair to make payers pay more fees to accomodate the recipient's wish for anonymity.
241+
It should instead be the recipient that pays the fees of the blinded hops (and the payer pays the
242+
fees to reach the introduction point).
243+
244+
For example, if a merchant is selling an item for `N` satoshis, it should create an invoice for
245+
`N-f` satoshis, where `f` is the fee of the blinded part of the route.
246+
247+
### Dummy hops
248+
249+
The sender knows an upper bound on the distance between the recipient and `N(0)`. If the recipient
250+
is close to `N(0)`, this might not be ideal. In such cases, the recipient may add any number of
251+
dummy hops at the beginning of the blinded route by using `N(j) = N(r)`. The sender will not be
252+
able to distinguish those from normal blinded hops.
253+
254+
Note that the recipient needs to fully validate each dummy hop to detect tampering.
255+
256+
### Wallets and unannounced channels
257+
258+
Route blinding is particularly useful for wallets that are connected to nodes via unannounced
259+
channels. Such wallets would use a single blinded hop, which effectively hides their `node_id`
260+
and `scid` from the sender. It obviously reveals to the blinded node that the next node is the
261+
final recipient, but a wallet that's not online all the time with a stable IP will never be able
262+
to hide that information from the nodes it connects to anyway (even with rendezvous).
263+
264+
### Blinded trampoline route
265+
266+
Route blinding can also be used with trampoline very easily. Instead of encrypting the
267+
`outgoing_channel_id`, we simply need to encrypt the `outgoing_node_id`.
268+
269+
Each trampoline node can then decrypt the `node_id` of the next node and compute `E(i)` for the
270+
next trampoline node. That `E(i)` can then be sent in the outer onion payload instead of using the
271+
message's TLV extensions, which is even cleaner.
272+
273+
## FAQ
274+
275+
### Why not use rendezvous
276+
277+
While rendezvous is more private, it's also less flexible: it doesn't support reusing the partial
278+
onion nor retrying with updated fees on intermediate node failure. Route blinding has different
279+
trade-offs, which makes it useful for slightly different use-cases than rendezvous.
280+
281+
Route blinding lets senders choose the amounts and cltv sent through each blinded channel: it makes
282+
payment success more likely, but introduces a probing surface for attackers.
283+
284+
### Why not use HORNET
285+
286+
HORNET requires a slow session setup before it can provide useful speedups. In cases where you
287+
expect to send a single message per session (which is the case for most payments), HORNET actually
288+
performs worse than Sphinx in latency, bandwidth and privacy.
289+
290+
## Open Questions
291+
292+
* Should we include feature bits in `encrypted_recipient_data`? It's yet another probing vector so
293+
we'd need to "sanitize" them to avoid reducing the node's anonymity set...
294+
* Should we add the `payment_hash` to the additional data authenticated by `encrypted_recipient_data`?
295+
* Should we include cltv and feerates in the `encrypted_recipient_data`? And use uniform fees/cltv
296+
accross the blinded path to protect against attacks leveraging multiple blinded invoices?

0 commit comments

Comments
 (0)