MindMapVaultMMV

Zero-knowledge architecture

Your maps are encrypted
before they leave your device.

The server stores only ciphertext. We hold no key, no password, and no readable content — by design, not just by policy.

AES-256-GCMArgon2id KDFML-KEM-768 post-quantumOpen-source crypto

Trust model

What the server can and cannot see

The security boundary is not a promise — it is a consequence of the architecture. The server never receives the inputs needed to decrypt your data.

Your browser
  • Your password
  • Master key (RAM only)
  • Private keys (decrypted)
  • Plaintext mind map
  • Map titles (plaintext)
auth_token (HKDF-derived credential)
Encrypted private key blobs
AES-256-GCM ciphertext blob
Encrypted title
Our server
  • Argon2id hash of auth_token
  • AES-wrapped private keys
  • Encrypted map blob (MinIO)
  • Encrypted title ciphertext
  • Public keys (public by design)

Core guarantees

Three things the architecture enforces

Password never transmitted

Your password runs through Argon2id locally to produce a master key. The server receives only an HKDF-derived auth_token — a credential mathematically separated from the password and from the encryption keys. Even if this token were stolen, it cannot decrypt any vault content.

Private keys never stored in plaintext

Your X25519 and ML-KEM-768 private keys are generated in the browser and immediately wrapped with AES-256-GCM(master_key, …) before being uploaded. The server stores the ciphertext. Without your master key — which never leaves your device — the blobs are meaningless.

Map content never readable by server

Every save generates a fresh Data Encryption Key (DEK) at random. The DEK encrypts your mind map with AES-256-GCM, then is itself wrapped using a hybrid classical + post-quantum KEM. The server stores the wrapped DEK and the blob — but has no input to unwrap the DEK. No key reuse across saves.

How it works

Encryption step by step

Registration — key derivation

Your password
+ random salt
Argon2id
64 MiB · 3 iterations
Master Key
32 bytes · RAM only
HKDF "auth-v1"
auth_token
→ sent to server
AES-256-GCM wrap
Encrypted private keys
→ stored server-side

The server hashes auth_token again with Argon2id before storing — so even the credential in the database is a derived hash, not the original token.

Saving a mind map — per-save encryption

Your mind map
plaintext JSON
AES-256-GCM
fresh DEK per save
Encrypted blob
opaque ciphertext
uploaded via HTTPS
Object storage
MinIO · no key held
Fresh DEK
random 32 bytes
hybrid KEM
X25519 + ML-KEM-768
Wrapped DEK
+ ephemeral pub key
stored in DB
Database
MongoDB · no key held

The DEK is never stored anywhere. It is re-derived on demand by the client using their private keys. Each save is independently encrypted — no key reuse between saves or between users.

Cryptography stack

Standard algorithms, audited libraries

AES-256-GCM
Symmetric encryption

Encrypts all content: mind map blobs, map titles, and private key blobs. Uses the browser's native Web Crypto API — no third-party symmetric crypto library.

NIST standard · Web Crypto API
Argon2id
Key derivation

Derives the master key from your password. Parameters: 64 MiB memory, 3 iterations, 4 threads. Implemented via hash-wasm (WebAssembly) — runs entirely in your browser.

Password Hashing Competition winner
X25519
Classical key exchange

Elliptic-curve Diffie-Hellman used for the classical half of the hybrid KEM. Generates an ephemeral keypair on every save — no long-term encryption key reuse. Implemented via @noble/curves.

RFC 7748 · @noble/curves
ML-KEM-768
Post-quantum KEM

The post-quantum half of the hybrid KEM. Standardised by NIST in 2024 (FIPS 203). Protects against future quantum computers that could break X25519 using Shor's algorithm. Via @noble/post-quantum.

NIST FIPS 203 · 2024 standard
HKDF-SHA256
Sub-key derivation

Derives domain-separated keys from the master key ("crypt-mind-auth-v1", "crypt-mind-title-v1", "crypt-mind-dek-v1") and combines the classical + post-quantum shared secrets. Via @noble/hashes.

RFC 5869 · @noble/hashes
Hybrid KEM
Key encapsulation

Combines X25519 and ML-KEM-768 shared secrets via HKDF: HKDF(classical_shared ‖ pq_shared). Security holds if either layer remains unbroken — a conservative, defence-in-depth design.

Classical + post-quantum combined

Data inventory

Exactly what is stored where

Server never sees
  • Your password
  • Your master key
  • Your private keys (plaintext)
  • Your Data Encryption Key (DEK)
  • Mind map content (plaintext)
  • Map titles (plaintext)
Server stores (all encrypted)
  • Argon2id(auth_token) — credential hash
  • Argon2id salt + params (needed by client to re-derive)
  • AES-256-GCM(master_key, x25519_private)
  • AES-256-GCM(master_key, mlkem_private)
  • AES-256-GCM(DEK, map_content) — MinIO
  • AES-256-GCM(title_key, map_title)
  • X25519 + ML-KEM-768 public keys (public by design)

If the entire database and object storage were stolen, an attacker would see only opaque ciphertext blobs and public keys. Without your password, the content is computationally infeasible to recover.

Threat model

Honest about what we protect — and what we don't

Protected against

  • Server compromise — DB and file storage contain only ciphertext. A breach exposes no plaintext.
  • Network interception — TLS in transit; payload is ciphertext regardless.
  • Credential theft — Stealing auth_token alone cannot decrypt any vault content.
  • Future quantum computers — ML-KEM-768 protects the key encapsulation against Shor's algorithm.
  • Cross-user replay — Each save uses a fresh ephemeral keypair and a fresh DEK. Ciphertexts are not reusable.
  • Admin reading your vaults — No decryption path exists server-side. Not a policy claim — an architectural fact.

Current limitations

  • Browser memory attacks — Code execution in your browser (e.g. XSS) could read the in-memory master key. Inherent to browser-based E2E encryption.
  • Password strength — Argon2id is strong, but a weak password is still a weak secret. Use a long, random passphrase.
  • No key rotation UI — Key rotation after a password change is tracked server-side but not yet exposed in the UI.
  • No audit log — Access events are not yet recorded. You cannot see what IP or device last opened a vault.
  • No credential recovery — If you lose your password for an encrypted vault, there is no admin-side recovery path. The data is cryptographically inaccessible.