Privacy On Lightning
Speakers: Bastien Teinturier
Date: November 17, 2021
Transcript By: freddiekrugerrand
Tags: Lightning, Privacy problems
Category: Conference
Media: https://www.youtube.com/watch?v=gOiKlx9a1xg
Slides: https://docs.google.com/presentation/d/1llk70vI2Mo5uQ7vnpfbl1qlr0qe0NLpySIelChIKhH4/edit
Introduction
Buenos Dias San Salvador, I’m Bastien. Hopefully my slides are going to come up. Oh yay, perfect. So I’m working on the Lightning Protocol Specification and one of its main implementation at Acinq.
I’m here to talk to you about privacy. This is a big topic. It’s not a black and white thing. There are various degrees of gray when you talk about what your threat model is, who you want to protect against. So what I’m going to be presenting is mostly the state of Lightning today, where the are privacy pitfalls, and what we can do about them, and what are the trade offs you can make and the solutions that we plan on deploying in the future.
I’ve been having some issues with slides, so I won’t have time to go into everything. I’ll keep the most complex stuff at the end. Let me know when I’m reaching the limit.
Aspects of Privacy in Lightning
One important thing to understand about privacy in Lightning is that there are two aspects to understand that are quite separate. There’s on-chain to off-chain aspect, where you want to be able to protect the privacy of the link between your on-chain stuff and your off-chain stuff. When you open channels you want to make sure that your on-chain and off-chain activities can’t be linked. And then there’s the privacy of what happens once you are inside the off-chain world, the off-chain to off-chain payments. These are quite distinct and don’t have the same trade offs.
On-Chain to Off-Chain
We’ll start off explaining what happens in the on-chain to off-chain part. I will not go into details about how Lightning works, because we’re talking about privacy. The only thing you need to know for now is that Lightning is a network. It’s just a big graph of nodes with edges between them and each of them is a Lightning channel with an on-chain transaction called a funding transaction which happens on-chain and has a UTXO which is backing that channel. Every one of these edges between points has a corresponding funding transaction on-chain. We’ll see a few things related to that. The only other thing that you need to know for privacy and this graph is that in Lightning we are actually announcing these channels to each other via a message called the channel announcement where we tell the network look there is this UTXO on-chain and it is opening a channel between this node and this node.
Let’s first focus on the funding transaction aspect. The way Lightning works today is that the funding transaction has an output which is a 2-of-2 multi-sig wrapped in a pay to witness script hash. When you create a channel you just broadcast this red transaction on-chain, and since it’s using pay to witness script hash, people watching the chain do no know it’s a Lightning channel. It just looks like any other pay to witness script hash on the network. When you close the channel and spend that output, you have to reveal the script that is wrapped in the pay to witness script hash. At that point everybody watching the chain knows that this was a 2-of-2 multi-sig, and these are not very common at all. When people see that on-chain, they can be pretty sure that this was a Lightning channel. This is bad. This is the kind of thing we want to avoid. Luckily, this one is very easy to fix with Taproot. I’m saying Taproot in many places, but we’re actually using Schnorr, not the script part of Taproot. It’s just here we will change the transaction, instead of using a pay to witness script hash we will use what Jonas just talked about, musig2. Instead of exposing the two different keys that went into this multi-signature, we’ll be using musig so it will just look like any other key path single signature spend on the network. Anyone looking at the chain will just see that this is one Schnorr signature, it could be anything.
The problem is that there are two ways we can close a channel on the network right now. There’s the cooperative close where both peers agree to build a new transaction that spends the funding output and spends it efficiently and redistributes the latest balance of the channel between the two peers. When that happens when they are building the transactions, they can hide the fact that they were using Lightning. There is also a way to close the channel unilaterally. This is really needed because you are dealing with multi-party protocol, you cannot trust that your peer will always be there to respond to you, to work with you to close the channel cooperatively. They could even disappear, go offline because their node has been destroyed, they have lost their keys. Or they could start being malicious, and start doing things to try steal your money. When that happens you have the option to do a unilateral close. What that does is it broadcasts a transaction that we call the commitment transaction on the network. What that does is exposes all of the internals of the Lightning protocol and your pending payments. That reveals a lot of scripts, that I’m showing here to show that they’re complex scripts that don’t look like anything else on the network. Whenever there’s a unilateral close, you’ll have to use these scripts to get your funds back. Even with Schnorr wizardry and improvements, that’s never something we’ll be able to hide completely from the network. These complex scripts are what guarantee the trustless part of Lightning, and they will always be custom to Lightning. We can make it better but we cannot completely hide it. Hopefully in the future when buggy implementations are not there anymore, this will only happen when your peer disappears due to catastrophic failure (which should hopefully not happen often), or if your peer is malicious (which should hopefully not happen often) because they would be able to gain nothing by being malicious.The problem is that there are two ways we can close a channel on the network right now. There’s the cooperative close where both peers agree to build a new transaction that spends the funding output and spends it efficiently and redistributes the latest balance of the channel between the two peers. When that happens when they are building the transactions, they can hide the fact that they were using Lightning. There is also a way to close the channel unilaterally. This is really needed because you are dealing with multi-party protocol, you cannot trust that your peer will always be there to respond to you, to work with you to close the channel cooperatively. They could even disappear, go offline because their node has been destroyed, they have lost their keys. Or they could start being malicious, and start doing things to try steal your money. When that happens you have the option to do a unilateral close. What that does is it broadcasts a transaction that we call the commitment transaction on the network. What that does is exposes all of the internals of the Lightning protocol and your pending payments. That reveals a lot of scripts, that I’m showing here to show that they’re complex scripts that don’t look like anything else on the network. Whenever there’s a unilateral close, you’ll have to use these scripts to get your funds back. Even with Schnorr wizardry and improvements, that’s never something we’ll be able to hide completely from the network. These complex scripts are what guarantee the trustless part of Lightning, and they will always be custom to Lightning. We can make it better but we cannot completely hide it. Hopefully in the future when buggy implementations are not there anymore, this will only happen when your peer disappears due to catastrophic failure (which should hopefully not happen often), or if your peer is malicious (which should hopefully not happen often) because they would be able to gain nothing by being maliciouse
The second aspect of the on-chain to off-chain part is this channel announcement that I talked to you about. The previous slides were only considering an attacker who was watching the chain. Actually, an attacker can do more. They can just run a Lightning node and they receive all the announcements for all these channels. Even if you have been able to hide on-chain the fact that this was using Lightning, you are actually doxing it in the Lightning Network by telling the whole world “look this is my channel, and this is the corresponding UTXO”, which is kind of bad. So, you may say that this looks bad at first but is not that bad because when you broadcast on the Lightning Network that there is a channel and there is a UTXO, and the channel is between two peers and only one peer is putting funds in the channel. You could say there is deniability because we don’t know whether it’s Alice or Bob’s funds, but in fact there is not. It’s really easy to figure out if it was Alice or Bob’s funds in the channel. For example, let’s consider change reuse. We start the funding transaction between Alice and Bob and announce to the network in that announcement that there is a channel between Alice and Bob and you think it’s okay because nobody knows whether it’s Alice or Bob’s. Usually there will be a change output in the funding transaction in the funding output. If Alice opens another channel using this change output with Carol, she doxes herself. Since it’s Alice who appears in both of these channels and not Bob, you know that the first channel was actually using Alice’s funds. It’s the same even if there is no change output, when you close the channel and you reuse your UTXOs. You get funds back on-chain, you want to do something with them. If you can’t use them, you’ve lost them. IF you use those to re-open a channel with Carol, you’ve exposed which output belonged to you, and what your balance was. You may think that it’s okay, just use CoinJoin, but it doesn’t help. If you start with the first channel, use the change output in a coin join, think you get new clean coins and then use it to open another channel with one of the same participants, then you just lost that privacy. People know that in the end that they can retract the path from Alice to Carol’s channel to Alice to Bob’s channel. You just did a coin join for basically nothing. You can do it in a more complex way to get more privacy, but this demonstrates that it’s really hard to correctly break the link between on-chain and off-chain if we keep on announcing our channels in the network. There is a solution to that, why do you announce these channels on the network? Just don’t tell the network about it. The reason we do that is that we need routing to work. The way that routing works in the Lightning Network is that everyone who runs a Lightning node is able to receive all these announcements and build a graph of the network locally. Everyone knows what the network looks like, when they want to send a payment they are able to just find a route in that graph and send a payment. If you don’t announce your channel, people will not know they can route through you. What happens if you’re not a routing node? You’re just a wallet sending and receiving, or a merchant who is just receiving, you don’t need to announce your channels, and you should not. If you don’t announce them, you’re protecting your on-chain privacy. Right now, all wallets don’t announce their channels, which is great. IT gives them more privacy than routing nodes. Even channels that are doing routing can use tricks so that they don’t need to announce all of their channels. Whenever you have multiple channels with the same peer, there’s no reason to announce all of them. You can just announce one of them and have other shadow channels with the peer and not announce them to the network. IT doesn’t give you perfect privacy, because the one you announce reveals one UTXO on-chain, but at least you don’t reveal all of them. However, this has a few negative impacts, because it means that the network will not see the complete capacity that you have between those peers. Right now, path finding heuristics use capacity to prioritize channels that are bigger, so you may be less prioritized in routing. Privacy is always a trade off, you have to give something in return for more privacy.
Unannounced channels are great for wallets because they are hiding the channels, but actually they are hiding their channels from the network but they are then doxing them in invoices. As a wallet you don’t need to tell the whole world about your channels, but when someone wants to pay you, they still need to be able to find you, and fund a route to you on the graph. You have to tell at least the payer that you have these channels that are not announced, but exist, so that they can use them to reach you. Right now the way it works is that we just include the channels in the invoices. If you only gave invoices to one payer, it would be kind of okay, even though once that channel is revealed, it’s revealed for eternity, which is bad. But people tend to post invoices on public places like Twitter, so they’re telling the whole world “look this is my private unannounced channel” and then everybody knows about it.
Fortunately we have a solution for that, and I will be shilling my own work here, it’s called route blinding. It’s a PR that I opened almost two years ago. It completely fixes this issue. I’ll try to give you an intuition of how it works, but there’s a lot of cryptography. It needs review, if you have time to review it please do, it’s on the lightning/bolts repo, I think PR 765. Referring to slides. If Alice wants to receive a payment, instead of telling the whole world that she has a channel with Bob, what she’s going to do is instead provide a route to herself which hides herself. She first starts by picking a route, saying that she wants to be paid through Carol then Bob. Then she’s going to do some crytpo magic to tweak all the node IDs of the nodes in that route so that they do not explicitly say this is Bob’s node ID, this is Alice’s node ID and this is a channel. She will tell Dave in the invoice that he has to find a route to Carol, and send Carol an encrypted blob that only Carol will be able to decrypt. When Carol receives that, she’s able to decrypt only that the next hop is going to be Bob. She doesn’t know what happens afterwards. Same for Bob, he’s able to decrypt that the next one is Alice. The important point is that what Dave sees, and the world sees when they have the invoice is just that the recipient is somewhere after Carol, looks like they are 3 hops after Carol. In the example given, Alice added a dummy hop to make it seem like she’s 3 hops away when she’s actually 2 hops away. The payer cannot know that, so it gives more privacy to Alice. The node IDs of that route is also not known to the payer. It’s better than hiding your channel because you’re also hiding your node ID. You can receive multiple payments without revealing that you’re the same person. Another important aspect of route blinding is that it’s a prerequisite for onion messages and offers, which c-lightning and Acinq are building. Which will hopefully be accepted soon.
Now we’ve seen most of the on-chain to off-chain stuff. At that point you kind of know how to protect these links.
Off-Chain to Off-Chain
Now we’ll move on to off-chain to off-chain, once you’re fully in the Lightning Network. How do you pay, what are the potential privacy issues and how do we protect against those?
So first off, just a quick reminder of how payments work in the Lightning Network. We are using onion routing, onion encryption, which is great. The scheme we are using is called Sphinx, it has security proofs. It looks like everything is perfect and it is protecting our privacy. What we’ll see is that we are leaking data outside of the cryptography which weakens the privacy guarantees of onion encryption. The way that onion encryption works is that the sender finds a route to the recipient. Referring to slides. Alice finds a route to Dave through Bob and Carol. She is going to encrypt in layers. She’s going to encrypt first something to Dave, then for Carol and put the one for Dave inside, then for Bob and send the message to Bob. Bob is only able to decrypt the outer layer of the onion, the part that is for him that reveals that he should forward something to Carol. Then Carol receives something and discovers that it is for Dave. When Bob receives the payment he knows it came from Alice, but he doesn’t know whether there were people before Alice, and he knows that it needs to got to Carol, but doesn’t know whether there are people after Carol. The same for Carol, and all the nodes in the route.
The way payments work in Lightning is that what you are actually paying for is the knowledge of a secret. We are using hash functions for now. The recipient says, here is the public part of a secret. If you pay me, I will reveal the secret part. Right now the only way we’re able to use it with Bitcoin is with hashes and preimages. Another good thing is that once you have this payment secret, you can use this as a payment proof that you actually made this payment. That is an important property that we want to preserve. The issue using payment hashes and preimages is that the payment hash we use is the same across the whole route. Everyone in the route sees the same thing. If an attacker controls multiple nodes in the route, he’s able to see that the payment is the same. We’ll see a bit later in the mobile wallet use case how that can be an issue and how you can identify senders and recipients if you are in the right places in the route. But fortunately this is also something that we can fix quite easily with Schnorr, as Jonas pointed out. We are going to move from HTLCs, these hash and preimage secret construction, to a point construction where instead of using hash functions we’re going to use arithmetic and elliptic curves. So when that happens, all the hops in the route will see a different secret. They will not be able to correlate that this is the same payment. One of the benefits of that is that before, with HTLCs, once the payment is complete, all the nodes in the route learn the secret (referring to slides). So all the nodes in the route would be able to say “look I have a secret, I made this payment”. Once we move to PTLCs, only the sender gets the real secret, and all the other nodes only know a kind of sub-secret that doesn’t let them prove that they were the ones to pay. This is a great improvement. This is something that will take a bit of time to deploy because there are a lot of things that need to be standardized and finalized first. If you have time and you are decent C programmer, you should review Jonas’s PRs on mu-sig and adaptor signatures which we will be able to use in Lightning.
So when you make payments today, most of the time you’re doing it from a mobile wallet. Mobile wallets have a very different privacy profile from routing nodes. One of the things that you will never be able to hide is that you are using a mobile wallet. You won’t be able to be online all the time, you won’t have a stable IP connection, you won’t be routing payments. The peers that you connect to know that you are a mobile wallet. When they receive a payment from you going somewhere else, they know that you are the payer, and not someone routing that payments. When they forward a payment to you, they know that you are the final recipient and that you’re not going to be relaying it further. No amount of cryptography and trickery will be able to change that. It’s just too easy to know that you are using a mobile phone. But, there are a lot of things that we can do to still make this a great privacy profile. I was mentioning the payment correlation attack, you see with hashes this is an issue. Referring to slides. If a mobile wallet user Alice is paying another mobile wallet user and the same guy is at the beginning and end of a route, since Bob knows that an outgoing payment is coming from Alice and at the end of the route a payment is going to Dave and he knows that they are mobile phones, he knows Alice is paying Dave. It gets better with PTLCs, because he still knows that Alice is sending and Dave is receiving, but doesn’t know that this is the same payment.
This one is a tricky one, more subtle and harder to pull off. Path finding can be exploited to weaken your privacy. If you’re a mobile wallet and connected to only one node and you are calculating your own routes themselves, the graph that you see is actually only what your peer let you see. Your peer can filter out some parts of the graph and only give the parts that he wants you to use. That means that he can force you, even if you are calculating your own route and thinking you have perfect privacy. If you are calculating routers on a subset of the graph that has been chosen by an attacker, this attacker is able to force you to take specific paths of the network that he controls. He may be able to weaken the privacy of your payments. Another interesting one is that MPP, multi path payments where you split a payment into multiple shards, can actually be bad for privacy if used naively. When a receiver, for example Dave, receives a payment that has been split into 3 parts, he can walk the graph back to figure out who could be at the point where it would make sense to split this payment in these three portions. He can realize that Bob is the most likely sender here, which is bad.
Fortunately there’s another solution that we proposed a while ago, more that two years ago, that is called Trampoline routing, which makes this a lot better. Unfortunately, I only have a few minutes, so I don’t think I’ll be able to go into all the details but I"ll start. The idea of trampoline routing is that mobile routing will not sync the whole graph. It doesn’t make sense on a mobile phone to sync a big graph with 1000s of nodes. It’s a poor user experience, it’s hard to do and calculating routes is inefficient. Mobile wallets are only going to sync their local neighborhood. Either only their direct peers, in which case they don’t see anything, or they can decide to sync all the network that is at least 2 hops away from them or 3 hops away from them. Only a subset of the network. Then what they’re going to do when they route is select a trampoline node in their neighborhood. The receiver is also going to select a few trampolines in their neighborhood and put that in their invoices. The sender will send the payment to the first trampoline node and tell it to find a route to the next trampoline node. This doesn’t reveal anything more than normal payments because it’s using the same onion encryption. It’s basically two layers of onion encryption. It doesn’t reveal more stuff about the payers or the receives, but it lets the payers calculate only the first part of a route, and the recipients only the last part of the route.
I’ll quickly go into an example here (referring to slides). If Alice wants to pay Dave, Dave is providing an invoice saying “you can reach me through Ted”. He is only syncing his neighborhood 2 or 3 hops away, and he sees that he is reachable through ted. Ted will not be able to know that he’s paying Dave, because Dave is not directly connected to Ted. When Alice receives that, she just knows she needs to use Ted as a trampoline node at the end of her trampoline node. Alice just finds a local trampoline node in her neighborhood, and she builds a trampoline route to herself through terry, ted and then to Dave. She sends a payment to Terry in green here, that was through bob. What bob sees is only a payment from Alice to Terry, but maybe to somebody else afterwards. HE doesn’t even know that trampoline routing is used. When terry received the payment, he sees that he’s being used as a trampoline node, and that he should find a route to Ted. HE doesn’t even see that Alice exists, only a payment from Bob. He only knows that he needs to go to Ted, but not what will happens afterwards. He finds a route to Ted through 1, 2, 3 and four. Each of these nodes when they receive a payment to forward, it just looks like a normal payment. They don’t even know that trampoline is being used, it’s just a normal payment. When Ted receives that payment, he knows that he’s being used as a trampoline. He doesn’t know the existence of Terry or Alice, the only thing he sees is that it’s a payment coming from N4 and he’s being asked to relay to Dave. He doesn’t know here because he’s not directly connected to Dave. He doesn’t know that Dave is a mobile wallet and that the payment could go even further than that. He finds a route to Carol and sends that from carol to Dave. There are some aspects here where I’m going a bit fast, because it actually needs route blinding to work perfectly.
I may have one minute to cover trampoline and MPP. What’s interesting with trampoline is that is makes MPP much better and much more private because each of the trampoline nodes are able to just aggregate all the multiple paths before forwarding. They can split it differently, which completely removes the attack I talked about here because every trampoline is able to split the payment differently, if an attacker were to analyze the graph backwards to discover that the payment seem to come from Bob the only thing he learns is that Bob is only a trampoline in the route. Bob could be any trampoline in the route. The attacker doesn’t learn anything more. It’s also a lot more efficient and a lot more reliable because every trampoline node has better knowledge of its local graph and balances. He’s able to relay more efficiently and find routes better than the original payer.
So perfect, I’ve been able to cover a bit fast at the end, but don’t hesitate to come see me if you have questions afterwards. Thank you.