post-quantum handshake, proof-of-work gated, secure ephemeral messaging
- JavaScript 75.6%
- TypeScript 8.4%
- Svelte 8.3%
- Go 7.1%
- HTML 0.4%
- Other 0.2%
|
|
||
|---|---|---|
| backend | ||
| frontend | ||
| favicon.ico | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
String Can
String Can is a proof-of-concept secure messenger that explores how small teams can collaborate with modern cryptographic primitives, zero-trust delivery semantics, and human-friendly guardrails. It currently consists of a Go backend, a SvelteKit frontend, and a Caddy reverse proxy configuration.
Features
- Post-Quantum Key Exchange: Clients generate ML-KEM (Kyber) keypairs and exchange wrapped content keys per message, so only intended recipients can decrypt payloads even if classical TLS is compromised.
- Automatic Participant Hygiene: The frontend polls the backend for up-to-date public keys and prunes inactive participants; rooms without active members expire automatically.
- Delivery Assurance: Outbound messages start optimistic but the client polls the backend if acknowledgements stall. It verifies remote receipts before prompting a manual retry.
- Proof-of-Work Gate: A simple hold-and-quiz challenge throttles automated abuse before exposing the UI.
- Traffic Light Status UI: Four-color indicators (link, typing, queued, ready) surface connection health and outstanding work at a glance.
- Invite-Friendly Rooms: Rooms are addressable via query-string tokens, with random city names and color-animal codenames for users.
- Transcript Export: Clients can save encrypted conversation snapshots (with metadata) for auditing.
Layout
backend/: Go HTTP + WebSocket API, PostgreSQL store implementation, Redis typing-notification integration.frontend/: SvelteKit application delivering the String Can UI, session handling, and PQC logic.frontend/static/: Favicon, manifest, and PoW assets.bio-site/index.html: Biography page referencing String Can as a proof-of-concept.
Backend Highlights
GET /session/anonymous: Issues throwaway session IDs and display names.POST /session/pqc: Registers client ML-KEM public keys.GET /rooms: Lists active rooms, pruning empty ones.POST /rooms: Creates a new room with a random ID.GET /rooms/:id/messages/:mid: Fetches message status and receipts for delivery polling.POST /rooms/:id/messages: Stores encrypted payloads and publishes them over WebSocket.POST /rooms/:id/messages/:mid/ack: Records delivery or read receipts.POST /rooms/:id/typing: Broadcasts typing events with TTL.GET|POST /rooms/:id/participants: Tracks membership and keeps participant key material current.- WebSocket
/ws: Streams room events (messages, receipts, typing).
PostgreSQL tables:
rooms,messages,message_receipts: Core delivery data.room_members: Participant roster with timestamps.session_keys: ML-KEM public key registry per session.
Frontend Highlights
- Stores:
sessionStorepersists identities across local/session storage and cookies;pqcStoremanages ML-KEM material;messageStorehandles optimistic sends + retries. - Components:
ChatPanelrenders the main UI, traffic lights, roster, message bubbles, and export/invite controls;GatePanelapplies the PoW challenge. - Auto-Healing: If participant keys are missing or an ack stalls, the UI triggers background refreshes before surfacing errors.
- Accessibility: Semantic headings, ARIA labels, keyboard-navigable controls; responsive layout for small screens.
Development
# Frontend
cd secure-chat/frontend
npm install
npm run dev
# Backend
cd secure-chat/backend
go run ./cmd/api
# Caddy (on production host)
sudo systemctl reload caddy
Environment variables (backend):
SECURECHAT_POSTGRES_URL– PostgreSQL DSN.SECURECHAT_LISTEN– Address (e.g.,:8080).REDIS_ADDR,REDIS_PASS,REDIS_DB– Optional typing notification cache.
Deployment Notes
- Backend binary lives at
/opt/secure-chat/securechat-backendmanaged bysystemd(securechat-backend.service). - Static frontend builds deploy to
/var/www/securechat/. - TLS certs are auto-renewed via Caddy; restart required only after code/config changes (
sudo systemctl reload caddy).
Roadmap
- WebSocket ack retries for peers behind unstable links.
- Optional automatic resend of failed messages after manual confirmation.
- Expanded telemetry dashboard (per-room participant activity, message delivery analytics).
- Hardened PoW challenge (allow pluggable validators or threat-level toggles).
String Can is intentionally experimental; treat it as a sandbox for testing PQC-handshake messaging, not a production-support SLA.