What we needed
AirSwap is a hybrid on-chain / off-chain protocol, which requires the coordination of off-chain peer-to-peer messages and on-chain identities (Ethereum addresses & private keys). If I’m chatting online with someone who claims to have control of an Ethereum address, I need to be able to cryptographically validate that they’re telling the truth.
We’ll call this first need off-chain/on-chain identity binding.
Secondly, since communication online is public by default, participants communicating with each other in a peer-to-peer network need to be able to hide their messages from everyone else, without trusting a central authority to coordinate encryption (public key registration).
We’ll call this need trustless end-to-end encryption.
Trustless end-to-end encryption enables another needed feature. If Alice is sending a message to Bob, and Bob is offline, Bob should be able to receive it when he comes back online, even if Alice no longer is. This means that a third party needs to be able to hold messages awaiting delivery in the interim. If the messages are encrypted, no one will be able to read them besides Bob and Alice, even if they are stored by a third party.
We’ll call this need encrypted offline delivery.
An industry standard for proving that you control an Ethereum address is to sign a challenge that someone sends you. Your signature can be used to prove ownership. However, if you’re communicating with many peers simultaneously (as is the design for the AirSwap protocol), this requires constant signatures, which is a tedious user experience when using a wallet like MetaMask, Ledger, or Trust Wallet. Messages can be signed programmatically when using a plaintext private key, but this exposes you to increased risk of being hacked. If we can keep our Ethereum private key secure inside of our wallet, and delegate only its ability to verify identity to another private key that can be stored in memory, we can automatically sign & decrypt messages without user interaction, and without exposing funds to increased risk.
We’ll call this needed functionality delegated programmatic authority
With the recent launch of AirSwap Spaces, we’ve put a system in production that not only fulfills all these needs but sets a new industry standard of what to expect from any messaging service with end-to-end encryption in terms of both security & convenience.
What we built
AirSwap KeySpace: trustless end-to-end encryption service
To illustrate the components involved in this system, I’ll show how they function together; both during key creation/recovery and during encrypted communication.
Key creation works as follows:
- The user signs a string unique to their address to generate a 164 char hex string. This is called the signed-seed. The signed-seed functions as a private key to encrypt the PGP private key in the PGP key pair.
- The app uses the openpgp.js library to generate a new PGP key pair encrypted with the signed-seed.
- The user stores a JSON blob with their encrypted PGP private key & PGP public key as a pinned file on IPFS.
- The user then stores the IPFS hash in the AirSwap PGP contract, which maps user addresses to IPFS hashes where their public keys can be accessed (and encrypted private keys can be recovered).
- Once the IPFS hash registration transaction has succeeded, the user is ready to send & receive encrypted messages.
- If the user wants to access their encrypted messages in a new context (i.e. using their Ledger wallet on a different computer), they can regenerate their signed-seed by using their wallet signature and use their signed-seed to decrypt their PGP private key stored on IPFS.
This is how the system functions during active use between Alice and Bob:
- On airswap.io, all direct messages need to be encrypted, so when Alice starts a new chat with Bob, the app looks up the IPFS hash of Bob’s PGP public key on the contract.
- Before sending a message to Bob’s Ethereum address, the app encrypts the message with Bob’s public key. It also attaches a copy of the message encrypted with Alice’s public key, so she can decrypt her sent messages at a later date.
- When Bob receives an encrypted message, the app decrypts it with his PGP private key (after decrypting it with his signed-seed).
This enables secure messaging, even in a decentralized public context, since the messages remain encrypted.
One of the main user experience gains with this approach is that in order to access their encrypted messages, all the user needs is control of the Ethereum private key. The user could have a ledger hardware wallet, and use it with multiple computers, and still have access to their encrypted messages on their new device. Functionally, we are using the entropy of your Ethereum private key signature to generate a sufficiently random secret for a PGP “brain wallet”.
For the more technical, a working implementation of the KeySpace system can be viewed in our developers repo.
We think this has big implications for the ecosystem, and are excited to see its use outside of what we’ve imagined.