Cover photo

The Three Layers of Encrypted Messaging and Where Each Should Live

Most apps say “end-to-end encrypted.” Almost none mean the same thing.


Most apps say “end-to-end encrypted.” Almost none mean the same thing.


When people say a messenger is “end-to-end encrypted,” they almost never mean the same thing.

WhatsApp says it. Signal says it. Telegram says it (sort of). Coinbase Wallet’s chat says it. Farcaster DMs say it. ANO says it. They all use the same words and ship dramatically different products.

The reason is that “encrypted messaging” isn’t one thing. It’s three layers, each with its own design choices, threat model, and trust boundary. Most apps make those choices implicitly and slap a single label on the result. The interesting builders make each choice deliberately and tell you exactly where their trust boundary sits.

This is a piece about those three layers, and what we’ve learned building ANO on Base about where each one belongs.

“Encrypted messaging isn’t one thing. It’s three layers, each with its own threat model.”


Layer 1: Identity Who Are You?

Before encryption can occur, both parties need verifiable identities. In a traditional messenger, identity is your email, your phone number, or your username, issued by a central authority (the platform), revocable by them, and tied to a real-world identifier they can subpoena.

In Web3, identity becomes a public key. You don’t need an email or a phone number; you have a wallet address, and that’s enough. Whoever controls the private key controls the identity. There’s nothing to subpoena from a server, because no server knows who you “are” beyond the address.

Identity belongs onchain. Specifically:

  • The public key is registered onchain so anyone can encrypt to you without going through a server.

  • The human-readable name (Basename, ENS, Farcaster username) is also onchain, it resolves to your address without a directory service in the middle.

  • Trust signals (reputation, mutual contacts, verified status) anchor onchain too, so they travel with the wallet across apps.

This is where the chain genuinely earns its keep. Identity is small (a few bytes), permanent, and benefits from immutability and global verifiability. Putting identity onchain costs almost nothing and gives the user something no Web2 app can: a portable, censorship-resistant identity that doesn’t disappear when the platform does.

ANO’s choice: all identity primitives, pubkey, nickname, Basename binding, trust score, live in onchain registry contracts on Base. No identity provider. No “Sign in with Google.” Your wallet is your account, end of story.


Layer 2: Transport How Does the Message Move?

Transport is where most apps quietly compromise.

A “fully onchain” messenger sounds appealing, every message a transaction, the chain as the post office. For text, it works: a 280-character message in calldata costs about $0.001 on Base. Cheap, censorship-resistant, permanent.

For the media, it falls apart. A 10MB voice note as a transaction payload costs dollars. Multiply by even modest usage, and you’re burning thousands per day in gas. No chain, no matter how cheap, makes media-on-chain practical at the consumer scale.

So transport has to split.

  • Text onchain. The chain is the message bus. Encrypted ciphertext sits in event payloads. Anyone can verify the message exists and was sent at a specific block. No central server can drop, alter, or intercept.

  • Media encrypted offchain. The chain holds a small commitment hash; the actual blob lives in an external storage layer. Could be cloud object storage, IPFS, Arweave, Filecoin, or anything else. The choice doesn’t matter much — because of layer 3.

The split is what most “fully onchain” projects don’t admit publicly. Be honest about it. The chain is the right place for some things and the wrong place for others. Pretending otherwise is theatre.

ANO’s choice: text rides on Base as encrypted event payloads. Media rides off-chain via an encrypted blob layer with on-chain access control. We commit a hash of the blob onchain, and the chain remains the source of truth for “who is allowed to read this.”


Layer 3: Content What’s Actually Inside?

This is the layer that should never compromise and the one where the term “encryption” earns its meaning.

Content encryption is what determines whether your messages are actually private. It’s also where the difference between “real E2E” and “marketing E2E” shows up.

Real E2E means:

  • Encryption happens on the user’s device, before the data leaves

  • Decryption happens on the recipient’s device, after the data arrives

  • No party in the middle server, storage, chain, ISP has access to the plaintext or the keys

  • Keys are generated and held client-side, derived from the user’s wallet

ANO’s choice: every message is encrypted client-side using an ECDH envelope (per-message key derived from sender + recipient), wrapped in AES-256. The recipient’s public key is fetched from the onchain identity registry. The sender’s private key never leaves the device.

For media: the client encrypts the blob before upload. The encrypted blob goes to storage. The storage operator sees ciphertext only. Even if the storage layer is compromised, leaked, or subpoenaed the operator gets noise.

“The choice of storage backend doesn’t change the privacy guarantee what matters is where the keys live.”

Crucially, the choice of storage backend doesn’t change the privacy guarantee at this layer. AES-256 + ECDH provides equivalent protection whether the ciphertext is stored in the cloud, on IPFS, on Arweave, or on a USB stick. The “decentralized storage” debate is mostly orthogonal to actual privacy; what matters is where the keys live, and the answer should always be “on the user’s device.”


The Auth Problem (or: Why You Don’t Need OAuth)

There’s a hidden fourth question most encrypted messengers fudge: how does the storage layer know whether to accept an upload or serve a download?

The Web2 answer is OAuth or some flavor of “Sign in with X.” The Web3 user came here to escape that. Asking them to sign in with Google to upload an attachment defeats the entire premise.

The Web3 answer is wallet-signature auth. The client signs a nonce with their AA wallet. The server recovers the address from the signature. The server checks onchain whether that address is allowed to upload to that path (sender or recipient of a chat, member of a group). No email, no OAuth, no third-party identity provider. Pure cryptography, all the way down.

ANO’s choice: every upload and download presents a fresh wallet signature. Authorization is checked against onchain state. Identity providers are not in the loop.


Why This Architecture Holds Up

The three layers of identity, transport, and content each live where they belong:

Layer Where it lives Why Identity Onchain Small, permanent, censorship-resistant Transport (text) Onchain Cheap, verifiable, no central operator Transport (media) Encrypted offchain Cost-practical, ciphertext-only Content Client-side Keys never leave the device Auth Onchain (signature) No 3rd-party identity provider

What this architecture doesn’t promise: it doesn’t hide that you sent a message. It doesn’t fully hide metadata. It doesn’t prevent compromised devices from leaking content. Anyone claiming otherwise is selling you something.

What it does promise: the content of your messages is readable by you and your counterparty, and nobody else. The infrastructure cannot read it. The chain cannot read it. The storage layer cannot read it. There is no key escrow, no recovery backdoor, no “trust us” hidden in the architecture.

That’s the honest meaning of “end-to-end encrypted.”


Where We’re Going

We’re building this on Base because Base sits in the only ecosystem where the four layers of on-chain identity, cheap text transport, off-chain media, and wallet-native auth all line up cleanly. Coinbase Wallet, Farcaster, Zora, and Aerodrome are each solving adjacent pieces. None of them has ended up at exactly this stack. Most of them shouldn’t. The split happens because each app optimizes for a different primary use case.

ANO’s primary use case is private deals: chat, agreement, and settlement in one thread. That use case demands all four layers to be honest about where they sit.

If you’re building anything in this space, we recommend the architecture above by default. We’ll keep publishing what we learn.

If you want to see it running, go to ano.ww8.io

.Private. Yours. Message.