Christian Decker [ARCHIVE] on Nostr: 📅 Original date posted:2019-04-04 📝 Original message: Hi ZmnSCPzj, I think we ...
📅 Original date posted:2019-04-04
📝 Original message:
Hi ZmnSCPzj,
I think we should not try to recover from a node not finding the next
hop in the trampoline, and rather expect trampolines to have reasonable
uptime (required anyway) and have an up to date routing table (that's
what we're paying them for after all).
So I'd rather propose reusing the existing onion construction as is and
expect the trampolines to fail a payment if they can't find the next
hop.
Let's take the following route for example (upper case letters represent
trampolines):
```
a -> b -> c -> D -> e -> f -> G -> h -> i -> j
```
With `a` being the sender, and `j` being the recipient. `D` and `G` are
trampolines. The sender `a` selects trampolines `D` and `G` at random
from their partial (possibly outdated) routing table. It creates the
inner onion using those two trampolines. It then computes a route to `D`
(`a -> b -> c -> D`). The `hop_payload` for `D` is a TLV payload that
has a single key `t` (assuming `t` is assigned in the TLV spec) that
contains the inner onion. It then initiates the payment using this
nested onion (`a -> b -> c -> D` + trampoline payload for `D`).
Upon receiving the onion `D` decrypts the outer onion to find the TLV
payload containing the `t` entry, which indicates that it should act as
a trampoline. It then decodes the inner trampoline onion and finds the
`node_id` of `G`. `D` then computes the outer onion to the next
trampoline `D -> e -> f -> G`, and adds the trampoline payload for `G`
(the inner trampoline onion we just decoded).
Upon receiving the onion `G` processes the onion like normal, finding
again an inner trampoline onion and decrypting it. Since `j` did not
indicate that it understands the trampoline protocol, `G` is instructed
to downgrade the onion into a normal non-trampoline onion (don't include
a trampoline, rather include the raw payload for `j`). It then computes
the route to `j`, and it creates a normal outer base routing onion `G ->
h -> i -> j`, which completes the protocol.
Like mentioned above the entire job of trampolines is to provide base
routing capability, and we should not make special provisions for myopic
trampoline nodes, since routing is their entire reason for existence :-)
Cheers,
Christian
>> Could this be implemented by replacing only the front of the trampoline-level onion?
>> (presumably with some adjustment of how the HMAC is computed for the new trampoline layer)
>
> I am trying to design a trampoline-level onion that would allow replacement of the first hop of the onion.
>
> Below is what I came up with.
> As I am neither a cryptographer nor a mathematician, I am unable to consider, whether this may have some problem in security.
>
> Now the "normal" onion, the first hop is encrypted to the recipient.
>
> I propose that for the "inner" trampoline-level onion, the first hop be sent "in the clear".
> I think this is still secure, as the "inner" trampoline-level onion will still be wrapped by the outer link-level onion, which would still encrypt it.
>
> When a node receives a trampoline-level onion, it checks if it is the first hop.
> If it is, then it decrypts the rest of the onion and tries to route to the next trampoline-level node.
> If not, then it is being delegated to, to find the trampoline.
>
> If the node cannot find the front of the trampoline-level onion, then it can route it to another node that it suspects is more likely to know the destination (such as the mechanisms in discussion in the "Routemap Scaling" thread).
>
> Let me provide a concrete example.
>
> Payer Z creates a trampoline-level onion C->D->E:
>
> C | Z | encrypt(Z * C, D | encrypt(Z * D, E))
>
> Then Z routes to link-level onion A->B->C, with the payload to C being the above trampoline-level onion:
>
> encrypt(Z * A, "link level" | B | encrypt(Z * B, "link level" | C | encrypt(Z * C, "trampoline level" | C | Z | encrypt(Z * C, D | encrypt(Z * D, E)))))
>
> Upon reaching C, it sees it is given a trampoline-level onion, and if C is unable to find D in its local map, it can delegate it to some other node.
>
> For example, if C thinks its neighbor M knows D, it can create:
>
> encrypt(C * M, "link level" | M | encrypt(C * M, "trampoline level" | D | Z | encrypt(Z * D, E)))
>
> M finds that it is not the first hop in the trampoline-level onion.
> So M finds a route to D, for example via M->N->D, and gives:
>
> encrypt(M * N, "link level" | D | encrypt(M * D, "trampoline level" | D | Z | encrypt(Z * D, E)))
>
> Is this workable?
> Note that it seems to encounter the same problem as Rendezvous Routing.
> I assume it is possible to do this somehow (else how would hidden services in Tor work?), but the details, I am uncertain of.
> I only play a cryptographer on Internet.
>
> Regards,
> ZmnSCPxj
Published at
2023-06-09 12:54:49Event JSON
{
"id": "cb274e7dac907637b5a94a68da8c2b1b44efef2df1e7f8f9e2a5f2c62feefe5f",
"pubkey": "72cd40332ec782dd0a7f63acb03e3b6fdafa6d91bd1b6125cd8b7117a1bb8057",
"created_at": 1686315289,
"kind": 1,
"tags": [
[
"e",
"60d26284fa5c438b86871bb223a7961f45c149bf53b3a176e75fc003d1d27577",
"",
"root"
],
[
"e",
"0f03b05a78ecd48688bddbc6f80a4f0ee3c0d7fb0d8d0f1373910b31588c997f",
"",
"reply"
],
[
"p",
"4505072744a9d3e490af9262bfe38e6ee5338a77177b565b6b37730b63a7b861"
]
],
"content": "📅 Original date posted:2019-04-04\n📝 Original message:\nHi ZmnSCPzj,\n\nI think we should not try to recover from a node not finding the next\nhop in the trampoline, and rather expect trampolines to have reasonable\nuptime (required anyway) and have an up to date routing table (that's\nwhat we're paying them for after all).\n\nSo I'd rather propose reusing the existing onion construction as is and\nexpect the trampolines to fail a payment if they can't find the next\nhop.\n\nLet's take the following route for example (upper case letters represent\ntrampolines):\n\n```\na -\u003e b -\u003e c -\u003e D -\u003e e -\u003e f -\u003e G -\u003e h -\u003e i -\u003e j\n```\n\nWith `a` being the sender, and `j` being the recipient. `D` and `G` are\ntrampolines. The sender `a` selects trampolines `D` and `G` at random\nfrom their partial (possibly outdated) routing table. It creates the\ninner onion using those two trampolines. It then computes a route to `D`\n(`a -\u003e b -\u003e c -\u003e D`). The `hop_payload` for `D` is a TLV payload that\nhas a single key `t` (assuming `t` is assigned in the TLV spec) that\ncontains the inner onion. It then initiates the payment using this\nnested onion (`a -\u003e b -\u003e c -\u003e D` + trampoline payload for `D`).\n\nUpon receiving the onion `D` decrypts the outer onion to find the TLV\npayload containing the `t` entry, which indicates that it should act as\na trampoline. It then decodes the inner trampoline onion and finds the\n`node_id` of `G`. `D` then computes the outer onion to the next\ntrampoline `D -\u003e e -\u003e f -\u003e G`, and adds the trampoline payload for `G`\n(the inner trampoline onion we just decoded).\n\nUpon receiving the onion `G` processes the onion like normal, finding\nagain an inner trampoline onion and decrypting it. Since `j` did not\nindicate that it understands the trampoline protocol, `G` is instructed\nto downgrade the onion into a normal non-trampoline onion (don't include\na trampoline, rather include the raw payload for `j`). It then computes\nthe route to `j`, and it creates a normal outer base routing onion `G -\u003e\nh -\u003e i -\u003e j`, which completes the protocol.\n\nLike mentioned above the entire job of trampolines is to provide base\nrouting capability, and we should not make special provisions for myopic\ntrampoline nodes, since routing is their entire reason for existence :-)\n\nCheers,\nChristian\n\n\u003e\u003e Could this be implemented by replacing only the front of the trampoline-level onion?\n\u003e\u003e (presumably with some adjustment of how the HMAC is computed for the new trampoline layer)\n\u003e\n\u003e I am trying to design a trampoline-level onion that would allow replacement of the first hop of the onion.\n\u003e\n\u003e Below is what I came up with.\n\u003e As I am neither a cryptographer nor a mathematician, I am unable to consider, whether this may have some problem in security.\n\u003e\n\u003e Now the \"normal\" onion, the first hop is encrypted to the recipient.\n\u003e\n\u003e I propose that for the \"inner\" trampoline-level onion, the first hop be sent \"in the clear\".\n\u003e I think this is still secure, as the \"inner\" trampoline-level onion will still be wrapped by the outer link-level onion, which would still encrypt it.\n\u003e\n\u003e When a node receives a trampoline-level onion, it checks if it is the first hop.\n\u003e If it is, then it decrypts the rest of the onion and tries to route to the next trampoline-level node.\n\u003e If not, then it is being delegated to, to find the trampoline.\n\u003e\n\u003e If the node cannot find the front of the trampoline-level onion, then it can route it to another node that it suspects is more likely to know the destination (such as the mechanisms in discussion in the \"Routemap Scaling\" thread).\n\u003e\n\u003e Let me provide a concrete example.\n\u003e\n\u003e Payer Z creates a trampoline-level onion C-\u003eD-\u003eE:\n\u003e\n\u003e C | Z | encrypt(Z * C, D | encrypt(Z * D, E))\n\u003e\n\u003e Then Z routes to link-level onion A-\u003eB-\u003eC, with the payload to C being the above trampoline-level onion:\n\u003e\n\u003e encrypt(Z * A, \"link level\" | B | encrypt(Z * B, \"link level\" | C | encrypt(Z * C, \"trampoline level\" | C | Z | encrypt(Z * C, D | encrypt(Z * D, E)))))\n\u003e\n\u003e Upon reaching C, it sees it is given a trampoline-level onion, and if C is unable to find D in its local map, it can delegate it to some other node.\n\u003e\n\u003e For example, if C thinks its neighbor M knows D, it can create:\n\u003e\n\u003e encrypt(C * M, \"link level\" | M | encrypt(C * M, \"trampoline level\" | D | Z | encrypt(Z * D, E)))\n\u003e\n\u003e M finds that it is not the first hop in the trampoline-level onion.\n\u003e So M finds a route to D, for example via M-\u003eN-\u003eD, and gives:\n\u003e\n\u003e encrypt(M * N, \"link level\" | D | encrypt(M * D, \"trampoline level\" | D | Z | encrypt(Z * D, E)))\n\u003e\n\u003e Is this workable?\n\u003e Note that it seems to encounter the same problem as Rendezvous Routing.\n\u003e I assume it is possible to do this somehow (else how would hidden services in Tor work?), but the details, I am uncertain of.\n\u003e I only play a cryptographer on Internet.\n\u003e\n\u003e Regards,\n\u003e ZmnSCPxj",
"sig": "85fe9a78c3a563ea8166f322b2884af26e21a98405691072d444c81a1e0ee22522eca09f8405aa869689cd1481451d3662efe907906948b0f86d6451f686bde3"
}