Skip to content

Repository files navigation

whisprChat

Self-hosted encrypted messaging for teams and individuals.

Whispr first emerged as a BILSEM graduation project. It is a project that I have been working on for many years, and as a result of the emergence of AI, I have made debugging and a few improvements with AI. I have now decided to make this project public, but this is still a project in development, community contributions are welcome.

Architecture

Component Language Purpose
Server Go WebSocket + REST API, SQLite persistence
Client Flutter Cross-platform UI (Linux, Android)

Features

  • End-to-end encrypted messaging with Signal and optional PGP direct messages
  • Real-time WebSocket communication
  • Group chats with per-member encryption
  • Self-hosted — your data stays on your server
  • Single binary deployment (~10MB)
  • Independently switchable Modern and Retro interfaces

Quick Start

Server

cd server
go build -o whispr-server
JWT_SECRET=0123456789abcdef0123456789abcdef ./whispr-server

Client

cd client
flutter pub get
flutter run -d linux    # Desktop
flutter run -d android  # Mobile

Normal client builds use the safe https://localhost:8080 default until the user selects another server.

Configuration

Environment variables for the server:

Variable Default Description
PORT 8080 Server port
DATABASE_PATH whispr.db SQLite database path. Existing whisper.db is reused automatically when present.
JWT_SECRET (generated) JWT signing secret
TOTP_ENCRYPTION_KEY (generated) Separate key for encrypting TOTP seeds; back up .totp_secret when generated
JWT_ACCESS_TTL 24h Access token lifetime
JWT_REFRESH_TTL 4320h Refresh token lifetime
HOST 127.0.0.1 Listen address; keep loopback behind a TLS proxy
ALLOWED_ORIGINS http://localhost:* Browser CORS/WebSocket origins
TRUSTED_PROXIES 127.0.0.1,::1 Proxies allowed to supply forwarded client IPs
LOG_FILE empty Optional JSON application log path. Leave empty to avoid app log files and use journalctl.
UPLOAD_DIR uploads Local upload storage path
ATTACHMENT_STORAGE_LIMIT_MB 360 Max encrypted attachment storage; full stores reject uploads without deleting history
FCM_CREDENTIALS_FILE unset Firebase service-account JSON for Android push notifications

See deploy/systemd/README.md for systemd paths, environment, logs, and the user-operated deployment workflow.

Signed client releases

The isolated release builder produces signed Linux x86_64 and Android arm64 artifacts without installing Flutter, Java, or an Android SDK on the host. It requires external Android and OpenPGP signing keys and never falls back to debug signing. See release/README.md.

Official artifacts are signed by the pinned 0xleitfader release identity. See release/SIGNING.md before trusting a downloaded build.

API

Authentication

POST /api/v1/auth/register   - Create account
POST /api/v1/auth/login      - Login
POST /api/v1/auth/refresh    - Refresh token
POST /api/v1/auth/logout     - Logout

Channels

GET  /api/v1/channels              - List channels
POST /api/v1/channels              - Create channel
POST /api/v1/channels/direct       - Find/create DM
GET  /api/v1/channels/{id}/members - List members
POST /api/v1/channels/{id}/members - Add member
POST /api/v1/channels/{id}/transfer-ownership - Transfer group ownership
POST /api/v1/channels/{id}/leave    - Leave a group

Messages

GET /api/v1/channels/{id}/messages         - Message history
POST /api/v1/attachments                    - Upload encrypted attachment bytes (`channel_id` required)

Public Keys

POST /api/v1/keys/signal-identity   - Publish a Signal device identity
GET  /api/v1/keys/prekey-bundle     - Claim a device prekey bundle
POST /api/v1/keys/pgp-public-key    - Publish an optional PGP public key

WebSocket

WS /ws

Authenticate WebSocket connections with the `Sec-WebSocket-Protocol` header:
`bearer, <JWT>` or `bearer.<JWT>`. Do not put access tokens in URLs.

Encryption Flow

  • Direct Signal messages use X3DH/PQXDH prekeys and Double Ratchet sessions, with ciphertext fan-out to each registered recipient device.
  • Group messages use Signal SenderKey. Distribution messages are themselves Signal-encrypted per recipient device; the server stores only ciphertext.
  • PGP is available as an optional direct-message mode. Private keys and local message/media caches are encrypted at rest with a platform-keystore key.

For remote deployments, terminate TLS with a reverse proxy, set PUBLIC_BASE_URL=https://chat.example.com, and never expose plaintext port 8080 to the internet.

License

MIT

About

A self-hosted secure messaging client with Signal Protocol and PGP support.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages