Skip to content

NobleChat

Private messaging over a real mix network with hybrid post-quantum encryption.

ci codeql license: AGPL-3.0

NobleChat encrypts every message end to end in the browser and routes it through a Sphinx style mix network, so the server never sees message content and cannot tell a real message from cover traffic. Keys are generated on your device and never leave it.

Status

This is a working project, not a finished product. The individual cryptographic primitives come from the audited @noble libraries, but the way they are composed here (the Sphinx layer, the packet and mailbox format, the account and multi device model) has not had an independent security audit. Do not rely on it to protect real secrets until that review has happened. See SECURITY.md for how to report issues.

New to the ideas behind it? The running app has a plain-language, animated explainer at /info.html.

What is inside

  • Hybrid post-quantum key exchange (X25519 + ML-KEM-768) and hybrid signatures (Ed25519 + ML-DSA-65).
  • A real mix network: layered mix nodes and providers, Poisson mixing, constant size packets, and cover traffic. Each node runs as its own process and only ever learns its own hop.
  • A zero-knowledge gateway: it only handles opaque onion packets, a mailbox id, public contact cards, a password hash, and an opaque (client encrypted) contacts blob.
  • Accounts with password login, multi device fan out, and durable offline delivery backed by PostgreSQL: messages wait in an encrypted mailbox until the recipient reconnects.
  • 1:1 and group chats, encrypted file and image attachments, auto-deleting images, message replies, emoji reactions and delete-for-everyone.
  • Voice and video calls over WebRTC, with the signalling carried end to end through the same channel.
  • A switchable transport: the built-in mix network, or the public Nym mixnet via an optional nym-client sidecar. The gateway falls back to the internal network if the sidecar is not reachable, and restores nym automatically once it reconnects.
  • An admin panel for announcements, maintenance mode, moderation, a server event log, runtime stats, mix node health and the transport switch.
  • Installable clients: a PWA (desktop, Android, iOS home screen) plus native desktop and Android builds produced by CI.

Architecture

browser client  --ws-->  gateway  --http-->  mix node L1 -> L2 -> L3 -> provider
   (crypto)              (accounts,            (each is a separate process,
                          mailboxes,            holds only its own key)
                          web, admin)                 |
                                                  delivers back to the gateway,
                                                  which pushes to the recipient
  • packages/crypto hybrid PQ primitives, AEAD, KDF.
  • packages/sphinx fixed size onion packet format.
  • packages/net mix router, directory, wire serialization, client helpers.
  • packages/protocol content and envelope framing.
  • apps/server the gateway (HTTP, WebSocket, accounts, admin, PostgreSQL).
  • apps/node a single mix node process.
  • apps/web the browser client and PWA.
  • clients/desktop Electron shell, clients/mobile Capacitor shell.

Quick start (self host)

Requires Docker and Docker Compose.

cp .env.example .env
# edit .env and set strong values for every secret
docker compose up -d --build

The gateway comes up on http://127.0.0.1:8790 (loopback only; set HTTP_PORT in .env if that port is taken). Put a reverse proxy (for example Caddy or nginx) in front of it for TLS. If your proxy lives in a different compose project, attach the noblechat service to its network with a docker-compose.override.yml instead of exposing the port. The compose file also starts the mix nodes, the providers, and a PostgreSQL database.

To route over the public Nym mixnet instead of the internal one, set NYM_CLIENT_URL=ws://nym-client:1977 in .env. That starts the bundled nym-client sidecar, which registers an identity on the Nym network (its data lives in a named volume, so the address is stable across restarts). Once the admin panel shows the sidecar connected, flip the transport there. Clients then load the Nym web client on demand and send over the mixnet; leaving NYM_CLIENT_URL empty keeps everything on the internal network.

Development

Requires Node.js 20 or newer.

npm install
npm test            # unit tests for crypto, sphinx, and the router
npm run build:web   # bundle the browser client

npm run smoke drives a RUNNING deployment end to end like a real browser client (register, subscribe, send through the mix, verify the sender signature, upload/download a file). Start the compose stack first, then:

SMOKE_URL=http://localhost:8790 npm run smoke

Clients

Open the deployment URL in any modern browser. To install as an app:

  • Desktop (Chrome or Edge): use the install icon in the address bar.
  • Android (Chrome): menu, then "Add to Home screen".
  • iPhone (Safari): Share, then "Add to Home Screen".

Tagged releases also build native desktop installers (AppImage, dmg, exe) and an Android apk and attach them to the GitHub release. iOS runs as a home-screen web app; a native App Store build would need an Apple developer account.

Security

Please report vulnerabilities privately. See SECURITY.md.

Contributing

Contributions are welcome. See CONTRIBUTING.md and the code of conduct.

License

AGPL-3.0. See LICENSE.

About

Private messaging over a real mix network with hybrid post-quantum encryption

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages