# 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`