E2EE chat behind Cloudflare with no MITM read + no in-flight poisoning
  • JavaScript 90.8%
  • CSS 5%
  • HTML 2.4%
  • Shell 1.8%
Find a file
ci a9f351d0c7 docs: add ARCHITECTURE.md — single clear reference for the whole system
One detailed doc covering the threat model, the two unlinkable planes, the exact
POST /api/mbx message wire format (double-sealed envelope), a full endpoint
reference, every feature, the state blob, the send sequence, and what the host
can/cannot see. Linked from README as the front-door reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 18:05:39 +02:00
client v4.12.0: full UI/UX redesign + tunable shield settings 2026-08-18 02:53:03 +02:00
deploy Ops hardening: off-box backup, offline signing key, tamper tripwire, onion UI 2026-08-16 18:16:54 +02:00
docs docs: add ARCHITECTURE.md — single clear reference for the whole system 2026-08-18 18:05:39 +02:00
ops v4.12.0: full UI/UX redesign + tunable shield settings 2026-08-18 02:53:03 +02:00
server harden: convergence round (iteration C, v4.9.0) 2026-08-17 05:56:14 +02:00
test v4.10.0: opt-in shielded rooms (L1-L3 capture-resistant rendering) 2026-08-18 02:18:15 +02:00
tools v4.10.0: opt-in shielded rooms (L1-L3 capture-resistant rendering) 2026-08-18 02:18:15 +02:00
.dockerignore harden: convergence round (iteration C, v4.9.0) 2026-08-17 05:56:14 +02:00
.DS_Store Feature: private groups + public/broadcast channels (E2EE, Cloudflare sees only ciphertext) 2026-08-17 00:52:54 +02:00
.gitignore Ops hardening: off-box backup, offline signing key, tamper tripwire, onion UI 2026-08-16 18:16:54 +02:00
AUDIT.md harden: convergence round (iteration C, v4.9.0) 2026-08-17 05:56:14 +02:00
DEPLOY.md harden: convergence round (iteration C, v4.9.0) 2026-08-17 05:56:14 +02:00
docker-compose.deploy.yml harden: deep audit round (iteration B, v4.8.0) 2026-08-17 05:13:53 +02:00
docker-compose.yml e2e-chat: E2EE-by-design chat (zero-dep server, WebCrypto client, signed releases, MITM audit tooling) 2026-08-16 13:43:11 +02:00
Dockerfile e2e-chat: E2EE-by-design chat (zero-dep server, WebCrypto client, signed releases, MITM audit tooling) 2026-08-16 13:43:11 +02:00
README.md docs: add ARCHITECTURE.md — single clear reference for the whole system 2026-08-18 18:05:39 +02:00

e2e-chat

End-to-end encrypted chat with accounts, invites, an admin panel and photo sharing, designed so a TLS-terminating proxy in front of it (Cloudflare) sees only hashes, ciphertext and metadata.

New here? Read docs/ARCHITECTURE.md — the single, detailed reference for how everything works (the two planes, every endpoint, the exact message wire format, and each feature). Then AUDIT.md (security model), docs/AUDIT-CF.md (malicious- Cloudflare proof), and docs/SHIELDED-ROOMS.md (screenshot-resistant rendering).

Live (deployed 2026-08-16, herbesvertes / .94)

  • Shell: https://e2e.ekaii.fr — Cloudflare DNS-only (gray cloud) so CF cannot alter the client code. LE cert, HSTS, strict CSP.
  • API: https://e2e-api.ekaii.fr — Cloudflare-proxied (orange cloud) for DDoS
    • WAF; carries only ciphertext/hashes. Verified end-to-end through CF (login, messages, SSE realtime, CORS, Full-strict TLS).
  • Tor onion (no CF, no IP): dckx5mrxeh2gypd7nppcui3nwfkhmkwuuat2i2ebpn3rnik6cpejjqqd.onion (serves shell + API same-origin via the nop-tor stack; use in Tor Browser).
  • Nym mixnet egress (Tier-3, hides IP + timing): nym-socks5:1080 on the coolify network; a SOCKS5 client reaches the app mixed (verified ~1.5s).
  • Container e2e-chat on the coolify network, docker-compose.deploy.yml, data in /srv/fast/services/e2e-chat/data.

v2 is metadata-private (see AUDIT.md v2 banner + docs/METADATA-PRIVATE-DESIGN.md): the server is a dumb mailbox/bucket store with no accounts, no membership, no sender in the message plane. Kuma monitors 131/132 alert on Discord.

Anti-poisoning is externally checkable at any time: node tools/verify-deployment.js https://e2e.ekaii.fr (PASS = live shell matches the Ed25519-signed release). Zero npm dependencies: the server is Node built-ins only (http, crypto, node:sqlite), the client crypto is pure WebCrypto in one file.

  • Security model, wire-format proof and honest limitations: AUDIT.md
  • Production topology and steps: DEPLOY.md

Quick start (Node >= 22.5)

node server/server.js
# first run prints a one-time admin invite code
# open http://localhost:8787, register with that code

Features

  • Username + password login where neither ever reaches the server (uid = PBKDF2-600k(username)+public salt; PBKDF2-600k + HKDF verifier).
  • Open registration (default) or invite-only; admin-granting invites.
  • 1:1 E2EE conversations, private groups, and public/broadcast channels (X25519 + Ed25519 identities, per-conversation AES-256-GCM key, sealed sender, signed messages). Group membership = knowledge of the conversation key: there is no cryptographic eviction/rekey, and a channel's key is shared with all users.
  • Optional forward-secret "disappearing" 1:1 chats (device-bound symmetric ratchet
    • X3DH prekey bootstrap; no post-compromise security).
  • E2EE photos with client-side thumbnails.
  • Verifiable display names inside the encryption (hash binding).
  • Key fingerprints, TOFU pinning, out-of-band verification, key-change alerts.
  • Max-privacy read is the default (the server can't tell which conversations you read).
  • Recovery key flow: password reset the server can neither read nor perform. It restores your identity keys; it does NOT restore the conversation list (that is password-derived) — peers re-invite after a recovery.
  • Admin panel: metadata-only user management, invites, disable/enable/delete (deleting a user does not revoke their access to conversations they were in).
  • Signed releases + integrity-checking service worker + external deployment verifier against in-flight code poisoning.

Test/audit tooling

node tools/mitm-proxy.js 8788 8787 test/capture.ndjson   # Cloudflare-position observer
node tools/audit-capture.js test/capture.ndjson test/canaries.json
node tools/gen-test-image.js test/photo.png
node tools/sign-release.js v1.0.0
node tools/verify-deployment.js https://e2e.ekaii.fr