LockerChat

Security

Our threat model, and the crypto behind it.

LockerChat is built on libsodium primitives. Here's what we protect, and what we can't.

What we protect

The things you'd expect from a private messenger, on by default for every user.

✉️

Message contents

Message bodies, attachment payloads, group topics, and avatars are encrypted client-side with libsodium before they reach the server. The server holds ciphertext for those. See the privacy page for the metadata the protocol does route on.

🔑

Encryption keys

Each device has its own X25519 keypair generated locally. Private keys never leave the device (not in backups, not over the wire, not to us).

🚪

Account access

Passwords are Argon2id-hashed before they ever leave your device. Session tokens are random 32-byte secrets the server only stores by SHA-256 hash.

📜

Disappearing history

Per-group TTL. The server sweeps expired messages every minute; clients purge them locally.

🚫

No public directory

No phone-number lookup, no email-based discovery, no contact-book uploads.

🔄

Forward-validating updates

Linked-device codes are single-use and expire in 5 minutes. Adding a device requires possession of an existing one or your password; never both bypassed.

🎭

Sealed sender

Sender identity isn't on the wire. Messages are signed inside the encrypted envelope so recipients can verify who sent them; the server never sees the sender's user_id or device_id on a relayed message.

What we don't protect

The things LockerChat does not (and cannot) give you.

Metadata

The server knows who is in which group and when each device fetches messages. We minimise what we keep, but the routing protocol needs some of that graph to deliver messages to the right devices.

Compromised devices

E2E encryption is end-to-end. If one of the ends is compromised (malware on your phone, an unlocked laptop) LockerChat can't help. Use a screen lock.

Forward secrecy (v1)

v1 uses static-key sealed-boxes. If a device key is later seized, prior ciphertext addressed to it can be decrypted. v2 will move to ratcheting (X3DH/MLS).

Coerced disclosure

We can't protect you from someone with your unlocked phone in their hand. Disappearing messages reduce the blast radius but don't eliminate it.

The crypto, briefly

Standard libsodium primitives. No homegrown algorithms.

crypto_box_seal (X25519 + XSalsa20 + Poly1305) + Ed25519 sig

Per-recipient sealed envelopes wrapping a payload signed by the sender's Ed25519 device key. Recipients verify identity from the signature; the server never sees who sent what.

crypto_secretbox (XSalsa20 + Poly1305)

Attachment payloads. The data key is wrapped per-recipient via sealed-box; the body itself is symmetric for performance.

Argon2id (libsodium pwhash, interactive limits)

Password hashing for account access. Memory-hard, side-channel-resistant, and tuned to make rainbow tables infeasible.

SHA-256 (session tokens at rest)

The server never stores raw session tokens. We keep only the hash, so a database leak can't be replayed against the API.

Want to go deeper?

The full protocol spec will be published alongside the public release.