Engineering inb0x

Parallel Life


End-to-end encrypted wallet-to-wallet communication

What we now know as inb0x began as a question: How would we build an application to handle wallet to wallet communication? A couple weeks later, a proof of concept was born.

What is inb0x?

Inb0x is a simple messaging tool built for web3. It uses end-to-end encryption to allow users to securely communicate to and from their Ethereum address. Users can connect to inb0x with their MetaMask wallet (more wallets coming soon), chat with the person behind a certain wallet, make offers on NFTs, and more. inb0x also makes use of ENS so users can contact wallets using their ENS address.

What does this have to do with a company building an NFT trading card game?

TCG’s are inherently social: trading cards, playing matches and talking strategy are at the core of the experience. Iterating on a product that provides secure, encrypted messaging and doesn’t tie users to an email address or phone number is directly in line with the overarching experience we’re envisioning.

Right from the get-go, there were a few challenges to overcome:

  1. We wanted this product to live on the web, but there is really no secure way to store plain text in the browser.
  2. Being an NFT project, we’re lucky enough to have a user base who is very familiar with Ethereum wallets. Relying purely on MetaMask for individual message encryption/decryption would have been very straightforward for us, however, forcing our users to execute a MetaMask transaction for every single message sent and received was out of the question.
  3. Private key security is paramount. Inb0x only uses officially supported methods in MetaMask. Your wallet keys are protected by MetaMask, always pay attention to what you’re signing/confirming.

How did we build it?

To reduce the number of interactions required by a user’s MetaMask wallet, users generate their own set of keys for message encryption (called the inb0x key pair). Security of the inb0x private key is critical — the unencrypted inb0x private key lives only in memory in the user’s browser.

1. First Time Using inb0x

The first time you interact with inb0x, you’re asked to perform 2 MetaMask actions.

  1. Sign a message to prove that you own your wallet. To reduce the number of MetaMask interactions, we create a ‘signed in’ wallet session for you, so you don’t need to re-sign until your session is terminated, or you switch wallets.
  2. Encrypt your inb0x private key. Every user generates their own inb0x key pair on the client side. The unencrypted private key is only ever stored in browser memory, inside of the encryption module, which is itself only defined in a closure). The module handles encrypting/decrypting the inb0x private key via MetaMask (using an official interface so wallet keys are never compromised). Unencrypted inb0x public keys are stored in our secure database (messages are encrypted with the destination wallet’s public key upon sending). Encrypted inb0x private keys are stored in our secure database so that senders can retrieve and decrypt their own key upon reconnecting to inb0x.

2. Subsequent Use of inb0x

On subsequent use of inb0x on any browser, users can retrieve their encrypted inb0x private key and their encrypted sent/received messages only after they have confirmed ownership of their wallet (via signing). Users then use MetaMask to decrypt their inb0x private key. Once again, this is using an official MetaMask interface — wallet keys never leave MetaMask. Once the inb0x private key has been decrypted it is only stored in memory. At this point a user can decrypt and read all of their messages.

Encrypted Message → Decrypted by inb0x private key → Decrypted by MetaMask

Of course, this is not completely foolproof if you have malicious extensions or code that you’re allowing to run in your browser then you could be exposing your inb0x messages and inb0x private key. To ensure that we don’t unnecessarily propagate private data to third parties, we don’t include any JS analytics/reporting libraries on

3. Sending Messages

When you send a message, you send two versions, one encrypted with the recipient’s inb0x public key, and one encrypted with your own inb0x public key. This way only you and the recipient are able to decrypt and read the message. Inb0x adds a salt to the contents of every message from within the encryption module which is especially important in securing short messages (i.e. preventing a brute force decryption of known/common short messages).

Additional Considerations

A common approach to secure messaging involves using a symmetric, shared key to encrypt all messages, and an asymmetric algorithm to encrypt the symmetric key. Because inb0x is web-based, there is no truly safe place to store this key. Now could we have kept it encrypted and synced it to the database each time? Could we even one-up this and get closer to Double Ratchet? YES, and it is definitely on the inb0x roadmap. This will allow for more flexibility in our messages, increased speed in our decryption and improved security.

A few of our users have been asking what we use to store the messages. We’re big fans of Elixir + Postgres at Parallel, but we wanted to keep the session system + database relatively lightweight so we can easily swap it out for a more decentralized solution, which made Firestore the perfect solution for the initial beta.

We had a lot of fun creating inb0x beta, and we welcome any feedback! Check it out at Also make sure to check out Parallel at

What’s in store for v1.0?

We’ve got a ton of improvements planned for v1.0 and onwards:

1. Address book with nicknames

2. UX improvements

3. Improved encryption and message formats

And much more!

UI Exploration — Sneak Peek

If you love building cool things and are interested in joining one of the fastest moving engineering teams in web3, we’re hiring!