If you’ve been paying attention to the Bitcoin space recently you’ve noticed the start of trend to swap out Bitcoin Addresses in the user interface with human readable identities using a decentralized key store (such as Namecoin). The first wallet to implement this (at least that I’m aware of) was RushWallet. I recently put out a video showing off a wallet I’ve been working on with Alon Muroch which more or less does the same thing. In my conversations with people I’ve been fairly surprised at the number of skeptics and harsh critics of this concept. So with this post I’m going to address the critics and go into much more detail of my ultimate vision for this technology.
How do you currently communicate your Bitcoin addresses to people so they can send you coins? If you are physically standing next to someone, you can have them scan your QR code. That would be the most secure way to go about it. But what if you don’t have physical contact with people? How do you communicate your addresses over the internet? If you’re like most people you probably just copy and paste your address and drop it in an email, Facebook message, Reddit post, etc. Whether you realize it or not, this is a terribly insecure way to communicate your address.
When you send a Facebook message, the message first gets sent to Facebook’s servers then routed to the recipient. Any malicious server admin or employee could fairly easily swap out your Bitcoin Address for their own before forwarding the message along to the recipient. The end result is the bitcoins get sent to a thief and not to you. So anytime you use this method for communicating your address, you are placing 100% trust in the server not to be malicious. With other methods of communication such as email or reddit post, there is an additional line of attack. Since these methods don’t secure the communication with the server with SSL the way Facebook does, you are exposing yourself to a Man-in-the-middle attack (MITM). Anyone with the right capabilities (such as your ISP) can intercept your traffic to the server, swap out your Bitcoin address for their own, and forward it along to the server.
Thus far we’ve been rather lucky these types of attacks really haven’t occurred. This is likely because it’s just easier to hack people’s computers and steal their coins that way. But should Bitcoin become more common place, you can rest assured all avenues for attack will be exposed.
Earlier this year the core developers unveiled the BIP70 Payment Protocol. Using this protocol you would send a signed payment request, including your address, to the recipient. The recipient’s wallet would check the signature against your public key to make sure the request is valid. If so, the address can be trusted to be legitimate. But how do you acquire the public key needed to verify the signature? The transmission of the public key can be MITMed just as easily as the address. Here the protocol employs X.509 certificates. A X.509 certificate is basically a public key which has been signed and independently verified by a trusted third party (a certificate authority). When you receive the certificate, your wallet will verify the certificate authority’s signature then proceed to verify the signature on the payment request.
But this seems like infinite regress. How do we acquire the public key of the certificate authority (the root certificate)? The answer here is it usually ships with your operating system. The wallet will verify the certificate authority’s signature against the root certificate in your OS’s root store. So to make the whole thing work, you have to trust both Certificate Authority as well as your operating system. In the vast majority of cases this level of authentication will be good enough as it’s fairly difficult to attack.
Right now, the payment protocol has caught on with the Bitcoin payment processors. If you’ve ever made a purchase from a merchant using, say, BitPay, with a compatible wallet (Bitcoin Core, Android Bitcoin Wallet, Hive) you’ve likely noticed the signed payment request. It works really well, and there’s a good reason to believe this will likely become the default payment mechanism for paying merchants.
My fear however, is that individuals are going to find it too cumbersome to sign up for X.509 certificates and will continue passing around addresses in emails, Facebook messages, etc. If I’m wrong here, then everything is fine. If I’m correct, we should probably come up with a more secure way for individuals to pay each other.
How About Web of Trust?
The problem of securely acquiring public keys isn’t new to Bitcoin. In PGP users have the option to use ‘web of trust’ to verify the validity of public keys. Imagine a scenario where Alice has downloaded Dan’s public key to send him an encrypted message, but she doesn’t know if she can trust it (it could have been MITMed). Charlie also has Dan’s public key and knows for sure it really is his (maybe he acquired it in person). Charlie can sign Dan’s key attesting to its validity. But this doesn’t help Alice at all because she doesn’t know or trust Charlie. But suppose Bob does know Charlie and has signed his key, and Alice knows Bob and trusts his key. Now Alice has a chain of trust that leads from her Dan and can trust Dan’s key.
The problem here is this sucks in practice. It’s very difficult (and a lot of work) to make enough trusted connections with people to verify all the keys you want to acquire. In the Bitcoin world where we want making payments to be seamless, this is unusable.
OneName as a Potential Solution
OneName is currently the most popular implementation of the concept of a distributed identity protocol. The basic idea is that you can take identity information (which can include a Bitcoin Address) and embed it into a block chain. Only the person in control of the private key can make changes and the data can then be downloaded from the block chain and acquired in a trustless manner. OneName is built on top of Namecoin, which is rather starved for development, but the alt coin isn’t of great importance. Another coin, such as Ethereum, could prove to be better for this purpose.
The idea here is that when you go to make a transaction, instead of entering someone’s Bitcoin address, you will type in a human readable name. The wallet will then use that name to query the blockchain and return the corresponding address. Here’s what it looks like in my wallet:
Looks great, but we aren’t without problems. First, currently the only way to get data out of the Namecoin block chain is to run a full heavyweight Namecoin node. This isn’t a viable option for most wallets (including mine) which are built to be lightweight and easy to use. Currently, what we do (this is pre-alpha mind you) is just query the OneName server, which in turn queries the blockchain and returns the address. But this brings us back to where we started ― placing 100% trust in a server. Just a little more fancy.
So we need to better way. What we can do here is to use the same Simplified Payment Verification (SPV) that lightweight wallets use. If you don’t know how this works, it was described by Satoshi in his white paper:
So what I would like to see is for either to guys running the OneName server, or someone else looking to improve on the idea, to implement SPV into the server. A wallet could query the server for the block headers. Then when querying for an address the server could return the full Namecoin transaction, the block it’s included in, and the Merkle proof. This would allow us verify the address really is in the block chain, and that the server didn’t just lie to us. I would build it myself, but I’m extremely busy with the wallet and authenticator.
Using SPV would eliminate just about all the trust in the server, but we still have problems. SPV only allows us to check if a transaction severed up to us is in the blockchain, but the server could still lie by omission. That is, refuse to serve up the latest transactions. In a Bitcoin wallet, this is semi-problematic. It basically amounts to a denial-of-service, but you don’t actually lose any money. You only fail to learn of some coins you actually received.
Lying by omission would be worse in the OneName context. It could mean that you might update your address in the Namecoin blockchain, and the server only tells other people of your old address. I don’t have a great solution here. I think the best we can do is make it a known rule that you need to retain the private keys for all addresses you upload into the block chain. If the server lies by omission, the payment still gets sent to an address for which you control the key. If you lose a private key, you will need to junk your name and create a new one to avoid placing trust in the server.
Who Am I Paying?
With most of the difficult stuff behind us, we still have the final issue of knowing who we are paying. How do I know that the +Mike I just sent coins to really is the Mike Hearn and not an impostor? Ideally Mike would tell me his OneName ID himself, preferably in person or over a secure communication channel. As long as he tells it to me, it doesn’t matter how many impostors are out there, I will still send the coins to the correct address.
But what if Mike doesn’t tell me his ID and I have to go searching for it? Well, this could be risky, but there are still things we can do to mitigate the risk. Right now OneName allows you to upload social media proofs to your profile. You can make a Twitter, Facebook, GitHub post basically saying “On OneName I’m +Mike”.
An impostor wouldn’t be able to fake that without access to your social media accounts. The impostor could post a fake URL to the proof such as:
But any wallet worth its salt would automatically check the proof and throw up a flag if it isn’t valid. We could even check that person has abandoned an ID this way. If you want to change IDs, delete your social media posts. The wallet will detect that the proofs are no longer valid.
In addition to social media verification, we could also do email verification. We’re all familiar with how email verification works. You enter your email into a website and it sends you an email with a link you need to click. OneName already does this when you sign up for name. The devs could easily sign your email address with their key and you could put the signature in your profile. The wallet could check the signature against their public key and prove your email is valid. This would require a trusted third party (a quasi certificate authority), but it would add an additional level of trust beyond just the social media proofs.
The only way someone could get scammed by an impostor after all this would be if they searched for a name (rather than having the person tell it to them) and didn’t personally know any of the social media accounts and proceeded to send the coins anyway. Obviously, it would be a best practice not to do that.
The final piece of the puzzle is stealth addresses. Everything I just mentioned above would work, but would have the major downside of requiring you to reuses addresses. For privacy reasons, we are trying to nudge people away from address reuse, not encourage it. For OneName to be viable, we have to get stealth addresses up and running. If you don’t know how stealth addresses work, they basically allow you to post a single public key (a stealth address) which the sender’s wallet uses to generate a new (regular) bitcoin address for which only you have the corresponding private key. The sender’s wallet sends the payment to that new address making the payment unlinkable to your stealth address in the block chain.
Full clients can be configured to work with stealth addresses with a little work, but the problem remains making them work with lite clients. Bitcoind nodes are not configured to serve up data related to stealth address. You could configure a server to work with stealth addresses ― this is the Dark Wallet approach ― but you need to take care to properly implement a prefix filtering scheme that will preserve the privacy of users. I’m not familiar with how Dark Wallet implements prefix filtering (if at all at this point), but I tend to be somewhat partial to this proposal by Greg Maxwell.
What I would really like to see is Bitcoin Core upgraded to handle stealth address, even if it’s just as a service bit, that way wallets can remain purely P2P and don’t have to resort to querying a server for the stealth transaction data.
I hope you can see that we’re a long ways from a viable implementation of OneName in wallets. Those who criticizing it are doing so extremely prematurely. But I believe I’ve laid out a mildly compelling case for how we can swap out addresses for human readable identities for individual payments and do it in a trustless and fairly secure manner. Hopefully I’m wrong about BIP70 and signed payment requests become the norm for individual payments, but if I’m not, this proposal should be a good substitute.
Feel free to comment with issues/security concerns.