Trust, demonstrated.
Manifa is end-to-end encrypted by construction, not by policy. Encryption happens on your machines; the server is a blind store. Here is exactly how — and where the honest limits are.
What the server never sees.
Everything content-bearing is ciphertext before it leaves your device. There is no server-side key that can reverse it.
What it does see.
We won't pretend metadata doesn't exist. The server learns a little — and we pad chunk sizes to blur even that.
- DATABASE_URL=postgres://…
- STRIPE_KEY=sk_live_…
- app.tsx
- schema.ts
- a3f1c08e…
- 9b27dd4a…
- 1f0e6c52…
- c84b91ff…
- 70a2e3d9…
A root key
only you hold.
At signup your device generates a 256-bit Account Master Key. It never leaves your machine in plaintext. The server only stores wrapped copies of it — sealed by a key derived from your password, by your recovery code, and by each device's public key.
Every Vault Key is wrapped by the master key. Per-chunk Chunk Keys are derived, never stored. It's the same model that backs Bitwarden and 1Password.
256-bit · never leaves your device
one per vault · wrapped by AMK
AMK sealed to each device key
derived, never stored
Boring crypto, on purpose.
No home-rolled ciphers. Standard, well-reviewed primitives composed carefully.
AES-256-GCM-SIV
Authenticated content encryption, nonce-misuse-resistant — the correct choice for the deterministic nonces convergent encryption requires.
Convergent, within a vault
A chunk key is HMAC(vault key, plaintext hash), so identical content dedupes — but only inside your own vault, so the cross-user confirmation weakness never applies.
XChaCha20-Poly1305 wrapping
Key-wrapping (master-to-device, vault-to-master) uses XChaCha20-Poly1305 with random nonces. Argon2id derives the wrap key from your password.
BLAKE3 content addressing
Every chunk is addressed by BLAKE3 of its ciphertext. The store is keyed by content hash; the server sees opaque IDs and bytes, never paths.
Who we defend against.
Learns nothing about file contents, names, or secret values. Sees only metadata it cannot decrypt.
TLS everywhere; payloads are already end-to-end encrypted underneath the transport.
Revoke it at the device level. Revocation deletes its wrapped keys and rotates the affected vault keys.
The honest limits.
Metadata leaks. The server learns chunk sizes and sync timing. We bucket and pad chunk sizes to blur it, but we don't claim it's zero.
True recovery means a recovery code. Because we hold no key, losing every device and your recovery code means the data is gone. We make backing it up unmissable at signup, but the math is the math.
A malicious server is out of scope for v1. Authenticated encryption plus Merkle-root verification detect forged ciphertext, but we don't claim Byzantine resistance to a server that actively serves bad data.
Encryption you can verify.
Dump our database and our object store and you'll find nothing but ciphertext. That's the bar we hold ourselves to.