Summary

This optionally fully decentralized messaging system allows messaging from a cryptocurrency address to any other cryptocurrency address. By asymmetrically encrypting messages, the system ensures that only the intended recipient is able to read the message, in most cases1.

Centralized vs. Decentralized

By hosting both the messages, and the client on IPFS, and using an ENS name as the domain name to access said client, most liability from the party running the system is removed, as there is no way to know any information about users2, including their names, email addresses, and even their IP address. There is also no way to control who can and cannot access the client3.

The optional centralization comes in with how the user’s “inboxes” are stored, and how the messages are stored. For the purposes of this document, “inbox” and “inboxes” refers to a database containing either:

  1. A mapping of addresses to a list of hashes of all messages sent to the address; or,
  2. A mapping of addresses to a list of encrypted messages sent to the address (may also optionally contain encrypted or unencrypted metadata)

It is probably prohibitively expensive to store inboxes in a decentralized manner, therefore to make this system practical, it may be necessary to store inboxes in a centralized database such as Redis or PostgreSQL. However, the inbox itself contains only enough information to find encrypted messages sent to users, so there is no significant downside for both the users and the party hosting the system if the inboxes are stored in a centralized way. In fact, it is likely more of a benefit to the users, as it reduces costs to send messages by 100%4.

Hosting the client can also be done in either a centralized or decentralized way. The messaging client can be a static website hosted on IPFS, which is assigned an ENS domain name. This would be fully decentralized. The alternative is to host the client on a regular server like any other website and have a regular DNS name point to the server. Optionally, an ENS name can be set to redirect to this DNS name.

Weirdly, it would likely be less expensive to host the client in a fully decentralized way, as it means no recurring costs for a server, and ENS names are typically less expensive than DNS names. Apart from the cost of the ENS name, the only fees from the decentralized hosting would be a small fee to update the ENS name when the client is updated. This fee would likely be less than a dollar, and updates can be restricted in order to reduce costs.

However, there seems to be a few problems with hosting a website on IPFS, namely that the entire website must be a single file. The obvious work-around being to link to external JavaScript and CSS files, but that would then no longer be fully decentralized, and those files would need to be hosted somewhere, likely at a (small) cost. In that case, since you need to store files in a centralized manner anyway, it seems like a better solution may be to host the entire website in an AWS S3 bucket. The cost to hosting a website in an S3 bucket is very minimal, if not completely free. It still requires a DNS name to point to the bucket, but it removes any possible server costs (apart from the aforementioned cost of the S3 bucket).

Implentation Basics

The client must at least allow a user to verify they own the address they wish to send the message from (‘from address’), allow the user to choose an address to send the message to (‘to address’), allow the user to write a plaintext message (‘the message’), and allow the user to send ‘the message’ from the specified ‘from address’ and to the specified ‘to address’. The client must also allow users to view the encrypted versions of any messages they have been sent. These features are the absolute minimum requirements for a client; obviously additional features can be added, so long as the base features remain.

Messages are sent to and received by cryptocurrency wallet addresses.

Sending the messages is a multi-step process:

  1. ‘The message’ is encrypted asymmetrically using ‘to address’ as the encryption key. This way you need the private key associated with ‘to address’ to decrypt the message.
  2. (Optional) The encrypted message is uploaded to IPFS.
  3. (If step 2 was done) The hash of the encrypted message, which is used to retrieve the message from IPFS, is saved to a database and paired with ‘to address’.
    (If step 2 wasn’t done) The encrypted message is saved in a database and paired with ‘to address’.
    The database can either be a centralized database such as Redis or PostgreSQL—obviously this would make the implementation no longer fully decentralized—or the database can be a smart contract (perhaps ERC-802, or something similar), for full decentralization, but higher costs.

The message is considered sent after these steps have been processed.

Receiving messages is also a multi-step process.
If the message is stored on IPFS:

  1. The user queries the database for the hashes of all messages addressed to a specific address.
  2. The user downloads each message from IPFS, using the hashes from step 1.
  3. The user decrypts any message they wish to read using the private key associated with the address they specified in step 1.

If the message is stored in a database:

  1. The user queries the database for all encrypted messages sent to a specified address.
  2. The user decrypts any messages they wish to read using the private key associated with the address they specified in step 1.

A more complex implementation

As well as all of the above, which is required for any functional implementation of this system, a more complex—and probably more user friendly—implementation would include the following:

  • A way for users to mark messages as read and/or delete messages that have been sent to the user. This way the user isn’t forced to have a cluttered inbox;
  • Timestamps on all messages;
  • A way to see what address the message was sent from.
  • A way to verify who the message was sent from (ex. a small message signed by the sender within the encrypted message, or within the metadata string).
  • Only allow users to view encrypted versions of messages they have been sent. Users can only read messages that were explicitly sent to an address they control, but messages may contain unencrypted metadata containing things like who the message was sent from (message metadata is described in a further section);
  • The ability to link an email address to an address in order to receive the messages sent to the address by email. A fully decentralized solution SHOULDN’T incorporate this, as it would mean the email address is publicly associated with the address, which would make this solution both no longer pseudo-anonymous, and redundant.

Message Metadata

Messages may contain an optional metadata string. It is recommended that the metadata not be encrypted, or if it is encrypted, that it be encrypted separately, if it will be used by the client for anything other than display purposes. This way it is impossible for the message sender to insert malicious code into the message that resembles a metadata string, and therefore may be accidentally executed as though it were a metadata string.

If the implementation does support metadata strings all messages MUST include a metadata string, however, it may be empty (ie. “{}”).

Metadata strings MUST be JSON encoded and be the absolute first thing in the message file, including whitespace.

The information required to be included in the metadata string (if any) is determined by the implementation, but ideally it would contain at least the time the message was sent, and who it was sent from. If the from address is included in the metadata it SHOULD also contain a short message signed by the from address, in order to verify the message was actually sent from that address.


1. Messages may be read by an unintended party in cases where the recipient's private key has been compromised, or other user error.

2. Depending on the exact details of the system's implementation.

3. Depending on the exact details of the implementation of the client.

4. Assuming the implementation doesn't require the user to pay to send messages.