Cryptography · threat model

How your memory stays yours.

We believe the right way to earn trust with a memory product is to write down what we actually do, pick honest words for it, and say the parts we explicitly don't yet claim. This page is the technical companion to the one-line promises on the homepage — algorithms, threat model, roadmap. No SOC2 boilerplate. No marketing euphemisms.

What we actually do.

Three structural properties, each a consequence of a specific architectural choice — not a policy we could change by editing a config file.

01 · No master key

No shared vault.

Every user's memory is encrypted with a key derived from their own credentials. There is no site-wide key that decrypts everyone. A full-database compromise alone decrypts nothing.

02 · Derived, never stored

Keys live only in request memory.

The per-user key is recomputed from the API key on every request via HKDF, used to encrypt or decrypt, then released to the garbage collector. There is no keyring file waiting to be exfiltrated.

03 · Per-user isolation

Compromise of one is compromise of one.

Because each user's data is encrypted with its own derivation, a leaked API key exposes only that user's memory. There is no blast radius beyond the account whose credential leaked.

The cryptography.

Kerckhoffs's principle: security should depend on the key, not on hiding the algorithm. Here's the full stack, with library versions so an independent reviewer can audit or reproduce.

PurposePrimitiveDetails
Data at rest Fernet AES-128-CBC with PKCS7 padding, authenticated by HMAC-SHA256. One token per encrypted record (JSON file or JSONL line). Ciphertexts are recognisable by the gAAAAA version prefix.
Key derivation HKDF-SHA256 32-byte derived key, salt=user_id, info=b"smtry-at-rest-v1", ikm=api_key. Deterministic and reproducible from the same inputs; rotating the API key invalidates the old ciphertexts by design.
Password hashing argon2id OWASP 2023 baseline parameters. Memory-hard so GPU and ASIC attackers don't get a speed advantage over legitimate login.
API-key tokens secrets.token_urlsafe Python's CSPRNG-backed URL-safe token, 32 bytes of entropy, prefixed anm_. Indistinguishable from random to an observer.
In transit TLS 1.3 Enforced at the edge (Caddy). Session cookies are HttpOnly, Secure, SameSite=Lax — the conservative defaults.
Library cryptography ≥ 44.0.0 PyCA cryptography — the reference Python implementation of the primitives above, audited and widely deployed. We don't roll our own crypto.

The threat model.

Every security claim is only as strong as the attacker it assumes. Here's what our architecture does and does not protect against — stated plainly so you can weigh the tradeoffs against what you plan to store.

We defend against

  • A database-only breach (encrypted ciphertext stolen without the user-record mapping).
  • A backup or disk snapshot leak (same ciphertext, same useless-without-key property).
  • Casual insider browsing — data at rest is unreadable without pulling a live API key.
  • Log-file inspection — we log metadata (timestamps, error codes), never plaintext memory.
  • Per-user compromise staying per-user — one leaked credential doesn't cascade.

We don't yet defend against

  • A full server compromise where an attacker simultaneously holds both the ciphertext and a live API key.
  • A determined operator with production shell access who decides to MITM a live request and capture the derived key in memory.
  • The LLM itself — once memory is retrieved and passed to Claude, it's subject to Anthropic's data handling, not ours.
  • A compromised client (your Claude Desktop, your browser, your laptop) — encryption ends where trust begins.

What we don't claim.

Anamnesis is not end-to-end encrypted.

True end-to-end encryption means the server never has the material to decrypt your data, even if it wanted to. Today, Anamnesis servers hold your API key (so they can authenticate you), and from the API key the server can derive your encryption key. That means a compromised or coerced server could decrypt your memory — it just can't do so from the ciphertext alone.

We won't call this "end-to-end" or "zero-knowledge" because that would mislead any reviewer reading carefully. The specific property we do provide — no master key, per-user derivation, no persistent key store — is already stronger than the generic "encrypted at rest" claim most SaaS makes. But it's not the same as the architecture Signal or Proton Mail use, and we're not going to pretend otherwise.

Phase 3 roadmap. Client-side key derivation — the browser or plugin derives the encryption key from a password we never see, and the server only ever stores ciphertext. This is a genuine architectural step (not a one-line change) and is tracked as the crypto Phase 3 in our engineering notes. We'll update this page the day it ships, with the same level of specificity.