How do I Know It’s Really You?
Verifying Authenticity of Public Keys
I have been personally involved with building applications using Public Key technology for more than 25 years. One of the most perplexing user experience problems I have had to tackle is the process of verifying that a public key has not been replaced by an imposter. We have fumbled through a variety of solutions in the past trying to please a wide spectrum of users from those who just want to post selfies to to the ultra paranoid crypto geek.
Let’s define some building blocks
Before we go too far let’s talk about some of the building blocks that we use in the development of great cryptographic apps like Storm4.
The Secure Hash
One of the most important concepts in cryptography is the secure hash function. There are lots of great hash functions to choose from, but they all have similar properties. They reduce a variable length string into a fixed length value in a deterministic way. Given the same input, it reproduces the same result over and over again. So let’s say we take all the text that comprises your favorite movie script, or the bits from your last instagram selfie photo, and run it through one of these hash functions like SHA-256. It would give us back a 256 bit value. This value obviously doesn’t hold enough information to derive the input that created the hash, its a one way process. Further because its a secure hash, any slight change in the input, like a pixel in the photo or a word in the script will result in a radically large change in the hash value. This coupled with using a hash that has enough bits, prevents the hash of the script from the original “Planet of the Apes” from colliding with the hash of a a slight revision of it, or worse a complete rewrite. We could even use the result of the hash function as an index to compare the source text against the hash of a duplicate of it without keeping the original text around.
The Public Key Algorithm
One of the other major building blocks that holds the internet together these days is Public Key Cryptography. Public key algorithms use mathematically derived pairs of values such that you can take some data an encrypt it with one key and decrypt it with the other. Not surprisingly we term one of these values a Public Key and the other a Private Key. Two of the important properties of these algorithms is that you can not derive much about the original message from encrypted data and that the process is not reversible without the possession of the private key.
Many of the Public key algorithms out there can also serve as a way to digitally sign data, in that the Private key can be used to produce a result that the Public key can verify. So given the original text, you can attach a series of bits that only could be created by the person who possess the private key and verified by anyone who has a copy of the public portion of the key pair.
In practice, Public key algorithms only work with a fixed number of bits, so typically its the secure hash of a text that is fed into the public key algorithm along with the private key to produce the signature.
Binding identity to a key.
To make public keys useful in the real world, we bind other information associated with the owner of that key; the owners email address, a user displayable name, the date a key was created or possibly an expiration date. All of this information can be fed into a hash algorithm in a predictable order along with the actual bits of the public key and the hash result signed by the private key. This is called the key self-signature or identity certificate.
That pesky middle man.
Assuming that all cool tech from public keys and secure hashes work and haven’t been hacked somehow, a question that presents itself is, “how do I know that the key that signed this message is not a fake.” To be more specific, how do I know that this message signature and the public key I am using to check it with are authentic.
Let’s look at how such a subterfuge can be orchestrated.
- Alice creates a key pair and publishes her public key on a server that she considers trustworthy.
- Alice then sends Bob a note that she signs with her public key.
- Bob receives a message from Alice for the first time, and intending to authenticate the message, request a copy of Alice’s public key from the same server.
- But somewhere along the line, a sneaky interloper hacks into the internet connection that Bob uses, intercepts Bob’s lookup for Alice’s public key and provides him with a counterfeit copy. Further this same scoundrel has modified Bob’s incoming message traffic to intercept and modify Alice’s messages and re-sign them with the counterfeit key.
- Bob won’t be any wiser of this ruse and for all practical purposes will find Alice’s modified message signature to be authentic.
What just described is a form of what is known as a Man in the Middle Attack (MITM). Traditionally defending against such an attack has employed one of two strategies or a hybrid of both: signing public key material with another public key you trust, or out of band key validation.
I mentioned earlier that public keys are just a series of bits and can be fed into a hash algorithm just like any other series of bits and the hash results can be compared to check against a known copy. This is how the earliest crypto applications verified key authenticity. Participants would manually compare the key hash results. Back then we were using the SHA-1 hash of 160 bits, which is 20 bytes or 40 hexadecimal characters. Sometimes we took a shortcut and only compared 8 or 16 of the hex characters. We even tried some other innovative approaches such as mapping the hash values to know word lists or mnemonic encoding. As smart phones with integrated cameras became popular we even experimented with bar code methods.
All of this was pretty tedious, easy to get this wrong and not something that you could sell to mass market. This fact became evident to me while I was developing secure communications apps at Silent Circle and PGP. No matter how we simplified it, most people simply ignored the hash comparison process altogether.
Signing public key with a trusted key.
For applications such as web browsers the canonical approach to verifying the authenticity of a public key is to sign it with another public key that you trust. These certificates are chained together with public key signatures signed by a trusted certificate authority in a hierarchal model. But how do we bootstrap the trust? The modern solution is to distribute the root public keys/certificates with the operating system or web browsers.
Of course none of this comes for free. With this model you pay rent for the signature on your public key from a certificate authority. (they have an expiration date). An entire billion dollar industry was pioneered by Verisign to perform this exact function. As a side note, somewhere in my garage I still have a floppy disks from the early nineties with my AOCE/PowerTalk developer RSA keys that Apple Computer signed.
Aside from the cost of signature, and the possibility that a certificate authority could misbehave and issue an unauthorized certificate, the hierarchal model isn’t always appropriate. As an alternative to the certificate authority the OpenPGP model allowed you to attach multiple signatures from other keys to your key creating a sort of Web of Trust model. You can even hybrid both hierarchal and web models to fabricate a trusted introducer model.
Either way, these modes require the signer to do some due diligence to verifying your key before signing, which brings us back to comparing hashes.
Enter the Blockchain.
There is so much information about blockchain technology available today, and I won’t attempt to waste any bits rehashing the topic here but leave it to the reader to dive into that topic. I would though like to make clear a few key concepts:
- A blockchain is an tamper proof ledger of records securely linked to previous entries using a cryptographic hash.
- Since the current entries hash included the previous entries hash, tampering with a past entry would invalidate any of the subsequent hash values.
- The blockchain is open to the public and widely replicated and distributed making tampering effectively impractical.
When I refer to the blockchain, I am specifically talking about the Ethereum distributed computing platform. What makes this platform so attractive is that the entries can consist of code or what is referred to as smart contracts. In addition to be executable on the blockchain platform, these smart contract functions can retain state between calls. Code that just reads state can be publicly executed, code that modifies state can only be called by the owner of the contract. The platform uses strong cryptography to verify that code that modifes the blockchain belongs to the owner of the contract.
The other thing that I find fascinating about the Ethereum platform is there is a complete micropayment economy attached to paying for code that modified the blockchain that provides incentive for people to put additional blockchain nodes on the network.
What we do at Storm4.cloud
Storm4 is a secure cloud storage platform that hosts zero-knowledge encryption. Your files are automatically encrypted on your device to your public key before being uploaded to the cloud. We can’t read any of your files. we can’t even see the filenames. And… only you hold the keys to decrypt your files. You can however, share these files with other customers of the Storm4 system by encrypting them to the recipients public key. And thus the point of this blog post. “How do I know that I am encrypting my file to the recipients actual key and that there is no man in the middle attack taking place?.”
Here is what happens when you create a trial storm4 account.
- You bind your Storm4 account to one or more social media accounts. (You can optionally create an account with no social media associations.)
- You are assigned a random 160 bit customer identifier (user id).
- The storm4 app (running on your device) creates a public/private key pair with your identity binding signed into the key, and uploads the public key to our server.
- We can not decrypt the data stored on cloud. The customer has the only working copy of the private key.
- We add an entry to the Ethereum blockchain binding the public key to that customer.
Blockchain-based public key verification
The process of getting your public key binding on the Ethereum blockchain requires a bit of work on our part. But the salient points are:
- We created a smart contract on the blockchain that takes the 160 bit/20 byte customer id and a hash of the user’s public key (typically SHA-256) and stores them together as a transaction on the blockchain.
- The smart contract code is open source. Anyone can examine it, and use it to verify a public key. But only we have the ability to write data to the blockchain with it.
- Once the transaction has been recorded to the blockchain, a transaction identifier is recorded and can be looked up by customers to verify the binding between customer ID and public key.
- All transactions are publicly visible and can easily be verified by both code and depending on your level of cypto paranoia, manually.
- Once posted on the blockchain this binding is inherently resistant against modifications.
What problem did we solve?
Well that was a lot of text. Pretty deep into TLDR territory. The bottom line was, we wanted to make it easy for our customers to feel confident and know their files are being securely encrypted to only their intended recipients. We were able to leverage modern blockchain technology to address one of the public key trust issues and make sure that no funny business is occuring.
If you want to dive into more details about how we got our code to talk to the Ethereum blockchain, we have a few posts that might want to read.
With Ethereum, it’s becoming a lot easier to put data on the blockchain. There are a variety of reasons why one might…medium.com
In part 1, we gave an overview of the Ethereum landscape, from the perspective of native app developers. And now we’re…medium.com