Security

Security model

What Encra protects against, what it doesn't, and why — with no marketing language.

Threat model

Encra is designed to protect message content even when the server infrastructure is fully compromised. The threat model assumes:

The Encra server may be compromised, subpoenaed, or malicious
Network traffic between client and server may be intercepted
An attacker may gain access to one party's session state

What we protect against

Server compromise

Server only stores public keys and ciphertext blobs. No plaintext, no private keys, no shared secrets. Even full server access yields nothing readable.

Network interception (MITM)

XSalsa20-Poly1305 is an authenticated cipher. Any modification to the ciphertext causes decryption to fail with DecryptionFailedError. The attacker cannot modify messages silently.

Key compromise revealing past messages

Message keys are deleted immediately after use (forward secrecy). An attacker who obtains today's ratchet state cannot decrypt past messages.

Key compromise revealing future messages

The DH ratchet generates new key material on every direction change. After the next DH step, the attacker loses access — they cannot decrypt future messages.

Weak randomness

All nonces and key pairs are generated by libsodium's randombytes_buf(), which uses the OS CSPRNG (getrandom on Linux, SecRandomCopyBytes on Apple).

Ciphertext malleability

Poly1305 MAC is computed over the entire ciphertext. Any bit flip is detected. The cipher is not malleable.

Limitations

These are real limitations, not disclaimers

Understanding what Encra does not protect against is as important as knowing what it does.

Compromised endpoint

If Alice's device has malware, the attacker reads plaintext before encryption and after decryption. End-to-end encryption cannot protect against a compromised endpoint — this is true of Signal, WhatsApp, and every other E2E system.

Metadata analysis

The server can see who is talking to whom, when, and how frequently — just not what they're saying. If you need metadata protection, you need an onion routing layer (Tor) in addition to Encra.

No key verification by default

Without comparing safety numbers out-of-band, a compromised or malicious server could substitute keys (man-in-the-middle). Use generateFingerprint() and verify with your peer through a separate channel.

In-memory key storage

By default, private keys are held in memory for the session duration. Page reload = new key pair. For persistent sessions, keys should be stored in IndexedDB with device-level encryption.

Cryptographic primitives

PurposeAlgorithmLibrarySecurity level
Key generationX25519 keypairlibsodium crypto_box_keypair128-bit
Key exchangeX25519 ECDHlibsodium crypto_scalarmult128-bit
Message encryptionXSalsa20-Poly1305libsodium crypto_secretbox256-bit key
KDF (ratchet)Keyed BLAKE2b-256libsodium crypto_generichash256-bit
Nonce generationCSPRNGlibsodium randombytes_buf256-bit entropy
Safety numbersBLAKE2b-256libsodium crypto_generichash256-bit

Why libsodium?

libsodium is a well-audited, portable cryptographic library used by Signal, Wireguard, and thousands of production applications. We use it instead of Web Crypto because it provides a consistent, misuse-resistant API across Node.js, browsers, and React Native. We never roll our own cryptographic primitives.

Security red lines

These are hard rules in our codebase. We never cross them:

Never log private keys, shared secrets, or plaintext messages
Never use a nonce/IV twice with the same key
Never store private keys in localStorage (use IndexedDB with encryption)
Never send private keys over the network
Never use non-constant-time comparison for auth tokens
Never roll our own cryptographic primitives — libsodium only
Never use Math.random() for anything cryptographic

Encra AI

Ask me anything · docs, code, troubleshooting

Hi, I'm Encra AI

I can explain concepts, generate starter code, troubleshoot errors, and guide your setup.

May make mistakes · verify critical crypto details