How RitChat works
RitChat is a minimal, file-based messenger with end-to-end encryption (E2EE). Encryption and decryption happen in your browser using WebCrypto. The server stores only encrypted payloads and a few unencrypted service events.
Chat identity (chat_id)
A deterministic id derived from the shared passphrase:
normalized = trim(passphrase).normalize('NFC')chat_id = hex(SHA-256(\"ritchat:chat-id:\" + normalized)).slice(0, 32)
Key derivation (PBKDF2)
- PBKDF2-HMAC-SHA-256
- Salt:
SHA-256(\"ritchat:kdf-salt:\" + normalized) - Iterations:
310000 - Key: AES-GCM 256-bit
Message encryption (AES-GCM)
- Random 12-byte IV per message
- AAD: UTF-8 bytes of
chat_id - Payload:
base64(iv) + \".\" + base64(ciphertext)
Transport and polling
- POST-only endpoints with CSRF protection
- Polling every 3 seconds
- Poll returns up to 200 events
Server storage
One file per chat under @runtime/ritchat:
{chat_id}.txt: JSON lines- Kinds:
msg,join,cleared msgincludes encrypted payloadptis a Unix timestamp in UTC (Greenwich)
Limitations
- Passphrase strength matters.
Retention
If a chat is inactive for more than 7 days, the server cleanup task removes its file.