Security
Public design document — derived from our internal architecture spec. Last updated: June 2026.
Blind Storage is zero-knowledge: all encryption and decryption happen on your device. The server and underlying cloud provider store and serve only ciphertext. Your master key is derived from your passphrase via Argon2id and is never transmitted.
┌──────────────┐ encrypted blobs only ┌─────────────────┐
│ Client App │ ──────────────────────────────▶│ Storage Layer │
│ (browser / │ │ (any S3-compat │
│ desktop / │◀────────────────────────────── │ provider) │
│ mobile) │ encrypted blobs only └─────────────────┘
└──────┬───────┘
│ key derivation, encrypt/decrypt
│ ALL happens here — never leaves device
▼
User's Master Key (Argon2id from passphrase)What we know: email (for auth), storage quota used, opaque blob IDs, padded blob sizes, approximate access times.
What we cannot know: file contents, filenames, folder structure, file types, exact file sizes, exact file counts.
| Principle | Implementation |
|---|---|
| Server never sees plaintext | All encryption/decryption client-side before upload |
| Server never sees filenames | Filenames encrypted inside the metadata vault |
| Server never sees folder structure | Hierarchy lives only inside the encrypted vault |
| Key derivation is client-side | Master key from Argon2id; never transmitted |
| Provider sees only ciphertext | Objects are indistinguishable encrypted chunks |
| Minimal metadata leakage | Fixed-size chunks; padded blobs; obscured timestamps |
User Passphrase
│
▼ Argon2id (salt per-user, iterations ≥ 3, memory ≥ 64 MiB)
Master Key (256-bit)
│
├──▶ Vault Key (HKDF-SHA256, info="vault")
│ └── Encrypts metadata vault (file index, folder tree, filenames)
│
├──▶ File Key per file (random 256-bit, wrapped by Master Key)
│ └── XChaCha20-Poly1305 encrypts file content
│
└──▶ Recovery Key (displayed once, stored offline by the user)
└── Can re-derive Master Key if passphrase is lostAll primitives come from libsodium (via libsodium-wrappers-sumo in JS and native bindings on mobile/desktop). We do not hand-roll crypto.
| Purpose | Algorithm | Why |
|---|---|---|
| Key derivation | Argon2id | Memory-hard; resists GPU/ASIC attacks |
| Symmetric encryption | XChaCha20-Poly1305 | 192-bit nonce; AEAD |
| Key wrapping | AES-256-KW (RFC 3394) | Wraps per-file keys under Master Key |
| Key agreement (sharing) | X25519 + HKDF | Ephemeral ECDH for secure sharing |
| Hashing | BLAKE3 | Fast integrity checks on chunks |
| Metadata encryption | XChaCha20-Poly1305 | Same AEAD for the encrypted vault |
| Authentication (login) | SRP-6a | Server never receives the passphrase |
Zero-knowledge products fail when users lose keys, not when crypto breaks. We ship:
If you lose your passphrase and your recovery kit, your files are unrecoverable. We cannot reset your password. This is by design.
| Threat | Mitigation |
|---|---|
| Server compromise | Server holds only ciphertext |
| Cloud provider subpoena | Provider sees only encrypted blobs |
| MITM | TLS 1.3; HSTS preload; cert pinning in native apps |
| Brute-force passphrase | Argon2id ≥64 MiB memory; SRP rate limiting |
| Rogue client update | Reproducible builds; code signing; open-source client |
| Metadata inference | Fixed chunks; padded blobs; no plaintext filenames |
| Ransomware / accidental delete | Object Lock + versioning + tombstone grace |
| Compelled backdoor | Open-source client; we architecturally cannot decrypt user data |
Client code will be open source at launch. Until then, this document is the public specification you can evaluate against.
Report a vulnerability
See SECURITY.md on GitHub or email security@blindstorage.com.