// onion-layered letters · 3 relays

Peel one layer.
Learn one hop.

Status: Mainnet livechecking…
// the working app

Open a mailbox. Wrap a letter. Watch it get peeled.

Every layer is built in this page with X25519 key agreement, HKDF-SHA256 and AES-256-GCM. The relays on this server peel the layers for real; the page then checks that each relay saw exactly the bytes it should have, and nothing more.

  1. STEP 1Open a mailbox
  2. STEP 2Wrap a letter
  3. STEP 3Send through 3 relays
  4. STEP 4Open it at the core
recipient

Your mailbox

Opening a mailbox makes a fresh X25519 keypair in this tab only and asks the server for a random mailbox id. The server never sees your private key; it only stores sealed letters it cannot read.

sender

Wrap a letter

Paste someone's mailbox card (or use your own to try it), write the letter, choose the route, and wrap it.

route shuffle
loading relay keys…
the onion you built

Layers, outside in

Each coloured ring is encrypted to one relay's public key with a fresh one-time key. The hash on each ring is what that relay should receive — the relay view below compares it with what the relay actually reports.

Wrap a letter to see its layers here.
transparency log

What each relay saw

After forwarding, this demo server reports back what each relay received and learned — something a real network would never do. It lets you check the claim: one layer each, one hop each.

hop 1 · entry

—

Not sent yet.
hop 2 · middle

—

Not sent yet.
hop 3 · exit

—

Not sent yet.
// how it works

Wrapped from the inside out, peeled from the outside in

  1. The sealed letter. Your text and optional pay-to address are padded to a fixed 1,536 bytes and encrypted to the recipient's X25519 public key: a fresh ephemeral key, ECDH, HKDF-SHA256, then AES-256-GCM bound to the mailbox id. Only the recipient's private key — which never leaves their tab — can open it.
  2. Three layers around it. Working outwards, the page wraps the letter for the exit relay ("deliver to mailbox X"), then for the middle relay ("next: exit"), then for the entry relay ("next: middle"). Each layer uses its own fresh ephemeral key, so the layers are unlinkable to each other by key.
  3. Peel, learn, forward. You hand the outer packet to the entry relay. It does ECDH with its own private key, decrypts its layer, reads only the next hop and passes the inner packet on. The middle relay does the same. The exit relay finds a mailbox id and drops in the sealed letter it still cannot read.
  4. Checkable, not trust-me. Because your browser built every layer, it knows the exact SHA-256 of what each relay should receive. The relay view compares those hashes with what the server reports, and the "wrong relay" and "tamper" tests show that a layer opens only for its own relay and only if unaltered.
  5. A real mainnet read. If the letter carries a pay-to address, the recipient can check its live balance and last activity on Solana mainnet through this site's read-only RPC proxy. Nothing is ever signed or sent.
// privacy model

Who learns what

PartySees your IPKnows the recipient's mailboxCan read the letterLearns
Entry relayyesnonothat you sent a packet, its size, and the middle relay
Middle relayno*nonothe entry and exit relays only
Exit relayno*yesnothe middle relay and the mailbox id
Mailbox storerecipient'syesnowhen letters arrive and are fetched; fixed-size ciphertext
Recipientno—yesthe letter and pay-to address — but not who sent it
The operator of all threeyesyesnoeverything about the path — which is why this is a demo, not anonymity

* In this demo every relay lives in the same process, so "no" means the relay's code has no access to it — not that the operator couldn't log it.

Kept out of relay sight

  • The letter text and pay-to address (end-to-end sealed to the recipient)
  • The full path: each relay only learns its neighbours
  • The letter's length: every letter is padded to the same 1,536 bytes
  • Your mailbox private key: generated and kept in your tab's memory

Still visible

  • Your IP address to the entry relay (and to this website)
  • Packet sizes per hop — they shrink by a fixed amount each layer, which reveals position
  • Timing: packets are forwarded instantly with no mixing or delay
  • A pay-to address is a public Solana account; its history is public on-chain

Onionpost reduces what any single relay can learn. It does not provide anonymity.

Known limitations — please read

  • One operator runs every relay. Real onion networks get their protection from many independent relay operators. Here one server hosts all three, so a dishonest operator could correlate every hop. Treat this as a teaching tool.
  • No cover traffic, mixing or delays. With so few users, timing alone links the sender to the delivery. Real systems add constant-size cells, batching and much more.
  • Relay keys come from this server. The page trusts /api/relays for the relays' public keys. The keys are regenerated every time the server restarts.
  • Senders are anonymous to the recipient — so is a scammer. Anyone with your mailbox card can drop a letter in. A pay-to address inside a letter proves nothing about who wrote it; confirm it through another channel before sending any funds.
  • Everything is in server memory. Mailboxes expire after 24 hours, hold at most 25 letters, and vanish on restart. Your mailbox key lives only in this tab: reload and the mailbox can no longer be opened.
  • Mainnet reads go through this site. The pay-to check and the live slot use this server's read-only RPC proxy, so the server sees which address you looked up.
  • Experimental and unaudited. Hand-written for this demo and not reviewed by anyone. There is no on-chain program and no token — the ticker is a placeholder label.