Security

Cryptographic Design

Public design document — derived from our internal architecture spec. Last updated: June 2026.

Trust model

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.

Zero-knowledge principles

PrincipleImplementation
Server never sees plaintextAll encryption/decryption client-side before upload
Server never sees filenamesFilenames encrypted inside the metadata vault
Server never sees folder structureHierarchy lives only inside the encrypted vault
Key derivation is client-sideMaster key from Argon2id; never transmitted
Provider sees only ciphertextObjects are indistinguishable encrypted chunks
Minimal metadata leakageFixed-size chunks; padded blobs; obscured timestamps

Key hierarchy

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 lost

Algorithms

All primitives come from libsodium (via libsodium-wrappers-sumo in JS and native bindings on mobile/desktop). We do not hand-roll crypto.

PurposeAlgorithmWhy
Key derivationArgon2idMemory-hard; resists GPU/ASIC attacks
Symmetric encryptionXChaCha20-Poly1305192-bit nonce; AEAD
Key wrappingAES-256-KW (RFC 3394)Wraps per-file keys under Master Key
Key agreement (sharing)X25519 + HKDFEphemeral ECDH for secure sharing
HashingBLAKE3Fast integrity checks on chunks
Metadata encryptionXChaCha20-Poly1305Same AEAD for the encrypted vault
Authentication (login)SRP-6aServer never receives the passphrase

Chunking & deduplication

  • Files split into 4 MiB fixed-size chunks; last chunk padded with PKCS#7 to the nearest 256-byte boundary.
  • Each chunk encrypted independently with a unique nonce derived from chunk index + file key — no nonce reuse.
  • Chunk ordering lives only inside the encrypted metadata vault.
  • Padding prevents the server from inferring exact file sizes.
  • No server-side dedup — identical plaintext produces different ciphertext (unique per-file key + unique nonces). Optional client-side content-addressed dedup within a single vault uses convergent encryption with a per-user pepper.

Recovery

Zero-knowledge products fail when users lose keys, not when crypto breaks. We ship:

  • Recovery kit PDF at signup — 24-word recovery phrase; upload disabled until confirmed saved.
  • Optional hardware-key unlock (WebAuthn) for power users.
  • Optional Shamir-split social recovery (e.g. 2-of-3 threshold).

If you lose your passphrase and your recovery kit, your files are unrecoverable. We cannot reset your password. This is by design.

Threat mitigations

ThreatMitigation
Server compromiseServer holds only ciphertext
Cloud provider subpoenaProvider sees only encrypted blobs
MITMTLS 1.3; HSTS preload; cert pinning in native apps
Brute-force passphraseArgon2id ≥64 MiB memory; SRP rate limiting
Rogue client updateReproducible builds; code signing; open-source client
Metadata inferenceFixed chunks; padded blobs; no plaintext filenames
Ransomware / accidental deleteObject Lock + versioning + tombstone grace
Compelled backdoorOpen-source client; we architecturally cannot decrypt user data

Audit plan

  1. Pre-launch: internal review against libsodium best practices; threat-model review.
  2. Beta: external audit by NCC Group or Cure53 targeting client crypto, API, and STS session policies.
  3. Ongoing: bug bounty; Dependabot; quarterly policy re-review.

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.