DEV Community

Cover image for I built a fully anonymous, E2E-encrypted P2P messenger that runs entirely in the browser #webdev #privacy #javascript #cryptography
PulseSOVP
PulseSOVP

Posted on

I built a fully anonymous, E2E-encrypted P2P messenger that runs entirely in the browser #webdev #privacy #javascript #cryptography

That's the whole relay. The operator genuinely cannot read messages — not because of policy, but because the math doesn't let them.

The honest tradeoff: the relay can see that a message was sent (metadata), even if it can't see what. For real anonymity you'd want onion-routing the fan-out. That's on the roadmap.

A few things I learned along the way

  • IndexedDB is a real database, not localStorage. Treat it like one. Versioned schema, compound index [conversationId, timestamp], cursor-based pagination. "Load last 50 messages" is O(log n) with the right index.
  • Service Workers can do encrypted push. The push payload itself is ciphertext, so the push service (FCM/Mozilla) only ever sees ciphertext. The SW decrypts and displays.
  • The pubkey is the identity. No username lookup table. The "Vault ID" users see is just a hash of the client's x25519 pubkey, generated in the browser. Free anonymity.
  • Don't roll your own crypto layer. I almost wrote a custom TweetNaCl wrapper. Then I realized I was reinventing tweetnacl-util. Just use it.

What's next

  • Native iOS / Android (federated, still no phone number)
  • Onion routing the relay fan-out
  • Per-message forward secrecy (real Double Ratchet, the Signal way)
  • Independent security audit
  • Open-sourcing the relay

Try it / AMA

If you want to:

  • Tell me the relay code is wrong
  • Argue X25519 vs Curve25519
  • Roast the "blind relay" claim
  • Share IndexedDB anti-patterns I might still have

The comments are open. AMA.

Top comments (1)

Collapse
 
pulsesovp profile image
PulseSOVP

by the way if you want to test my pulse id:founder you can add and write