Encryption model
Cove uses a server-trusted model. This page spells out exactly what that means.
Key hierarchy
Section titled “Key hierarchy”- Master password (
security.master_password): generated on first start if empty, or supplied viaCOVE_MASTER_PASSWORD. - Key-encryption key (KEK): derived from the master password with Argon2id.
- Data-encryption key (DEK): encrypts the BadgerDB database at rest. It is stored wrapped by the KEK.
- Channel keys: each channel has a unique AES-256 key, generated by the server, stored wrapped by the KEK and sent to authorized members over their authenticated connection.
Messages
Section titled “Messages”Clients encrypt messages with the channel key (AES-256-GCM) before sending. The server stores and routes ciphertext. Because the server holds the channel keys, the operator of the server can decrypt messages. This is deliberate: it makes multi-device sign-in, history and account recovery work without a key-verification ritual.
What this protects against
Section titled “What this protects against”- A stolen disk or database backup (data is encrypted at rest and useless without the master password)
- Network eavesdropping (use HTTPS in front of the server)
- Other users reading channels they are not members of
What it does not protect against
Section titled “What it does not protect against”- A malicious or compromised server operator
- Someone with both the database and the master password
WebRTC media is encrypted hop by hop with DTLS-SRTP between each client and the SFU. The SFU forwards media, so it is not end-to-end encrypted. Raw UDP mode is not encrypted at all and is meant for trusted LANs.
When you need more
Section titled “When you need more”Use Whisper for conversations where the server must not be able to read or retain anything.
Web authentication
Section titled “Web authentication”Browsers use an httpOnly cove_session cookie plus a double-submit CSRF token (cove_csrf cookie echoed in the X-CSRF-Token header). The desktop app uses a Bearer token instead. Passwords are hashed with Argon2id.