Table of Contents

v0.2.4 - E2E Message Encryption

Features

E2E Message Encryption

  • Application-layer AES-256-GCM encryption for all message content between client and server
  • Protects against ISPs, proxies, and any middleman reading chat messages — even if TLS is compromised
  • 256-bit encryption key auto-generated on first server startup and saved to appsettings.json
  • Client fetches the encryption key automatically after login via GET /api/server/encryption-key
  • Client encrypts messages before sending via SignalR; server decrypts for validation and processing
  • Server broadcasts encrypted content to SignalR clients; client decrypts transparently — no user action required
  • Optional database encryption at rest via Encryption:EncryptDatabase setting (disabled by default)
    • When enabled: new messages encrypted before DB storage (existing plaintext messages are not retroactively encrypted)
    • When disabled: messages stored as plaintext, no risk of data loss from key rotation
    • Reads handle mixed content (encrypted + plaintext) regardless of setting — safe to toggle at any time
    • Key rotation is safe: old plaintext stays readable, new messages use the new key
  • IRC gateway automatically decrypts messages before forwarding to IRC clients (plaintext over IRC)
  • Encrypted content format: $ENC$v1${nonce}${ciphertext+tag} (Base64, 12-byte nonce, 16-byte auth tag)
  • Server strips $ENC$ prefix from user-typed messages to prevent format spoofing
  • Graceful fallback: if decryption fails, shows [encrypted message — decryption failed, try re-logging to fetch the latest key]

Infrastructure

  • IMessageEncryptionService interface in Core; MessageEncryptionService server implementation and ClientEncryptionService client implementation
  • EncryptionKeyResponse DTO and GET /api/server/encryption-key endpoint (authenticated, rate-limited)
  • FirstRunSetup.EnsureEncryptionKey() auto-generates AES-256 key on first server run
  • Encryption:EncryptDatabase server setting (default false) controls whether messages are encrypted at rest
  • DB column max lengths increased for encrypted content: Message.Content 2000 → 16000, Message.EmbedJson 8000 → 32000
  • EF Core migration: AddEncryptionSupport
  • Encryption test suite: server-side, client-side, and cross-compatibility tests
  • Documentation article: docs/articles/encryption.md