Don't trust. Check.
This page states what Keepsake protects against, what it doesn't, and how to verify our claims yourself. Honesty is the point.
Architecture in one paragraph
Keepsake is local-first and zero-knowledge by construction. Your documents are encrypted with AES-256-GCM on your device, under keys derived only from things you hold (your password, recovery phrase, or your device's hardware keystore). Encrypted data is stored on your device and — if you enable sync — in your own Google Drive or OneDrive. Keepsake the company operates no document servers. We cannot read, lose, leak, or be compelled to hand over your documents, because we never possess them in any form.
What we protect, and from whom
A security page that lists only wins is marketing. Here is the full table, including the ❌ rows.
| Threat | Protected? | How |
|---|---|---|
| Stolen or lost laptop/phone | Yes | Everything AES-256-GCM encrypted at rest; keys derived via Argon2id from your password; auto-lock wipes keys from memory |
| Cloud provider reading your synced vault | Yes | Google/Microsoft store only ciphertext blobs; keys never leave your devices |
| Keepsake (us) reading your data | Yes | Structurally impossible — no servers hold your data or keys |
| A data breach at Keepsake | Yes | Our website database contains at most your email and license record — never documents or keys |
| Ciphertext tampering (malicious cloud, MITM) | Yes | GCM authentication plus AAD binding; modified files fail decryption loudly |
| Replaying an old vault state | Yes (local) | Index generation counter — a device refuses to load older state than it has seen |
| Secure Send link interception | Yes | Encrypted client-side; the key travels in the URL fragment, which browsers never send to servers; optional PIN; burn-after-read |
| Audit-log falsification | Yes | Hash-chained audit records, verifiable in Settings |
| A weak or guessed password | Partial | Argon2id (memory-hard) makes offline guessing expensive; a strength meter nudges you — but we cannot stop you choosing "123456" |
| Malware on your unlocked device | No | No app can defend a compromised OS with the vault open. Keys are held only while unlocked and zeroed on lock, which limits the window |
| Forgetting your password AND losing the Recovery Kit | No | Zero-knowledge means exactly that: nobody — including us — can reset it. Treat the Recovery Kit like cash |
| Coerced unlock ("rubber-hose") | No | Out of scope (Travel Mode limits what a device carries across borders) |
Cryptography
- Encryption: AES-256-GCM, random 96-bit nonce per file, AAD binding ciphertext to document identity. No unauthenticated modes anywhere.
- Key derivation: Argon2id (64 MiB / 3 iterations / 4 lanes on desktop, tuned per platform); parameters stored openly in the vault manifest.
- Envelope keys: a random 256-bit Master Key encrypts data; your password, recovery phrase or biometric key only wrap it. Password changes never re-encrypt your documents.
- Recovery: a 24-word BIP-39 phrase (printable kit with QR) wraps the same Master Key.
- Biometrics: Windows Hello / Android Keystore hold a hardware-backed wrapping key; biometric data never touches Keepsake.
- Passkeys and security keys: in the web app and in the Windows app, WebAuthn's PRF extension makes the authenticator produce 32 bytes that only that credential can produce; HKDF over them — with the vault id in the info string, so one key can hold slots on several vaults without sharing a secret — is the wrapping key. A passkey therefore opens the encryption, not a login: no server is asked whether you may proceed. A key a device holds is never the only way in — enrolling is refused until a password or recovery phrase exists, and removing the last way in is refused outright. The Windows app asks the key for the same function directly over CTAP2, where it is called hmac-secret, and reproduces the hash a browser applies to the salt before passing it on — which is what makes one physical key open the same vault on both surfaces rather than two keys that merely look alike (how it works). The Android app does not take a security key.
- Licenses: Ed25519-signed, verified offline; the license system knows your email, never your data.
- Boring on purpose: AES-GCM, Argon2id, HKDF, SHA-256, Ed25519, BIP-39 — no home-made crypto.
How to verify us
- The format is public. The vault format documents every byte — an independent tool can decrypt your vault with your password alone. Read the specs: Vault Format v2 · Security Model · Secure Send protocol.
- Network transparency. Run the apps behind a proxy: you'll see traffic only to your chosen cloud provider. License checks are offline; there is no telemetry endpoint to find.
- Download integrity, without trusting this website. Every release is published with a manifest of SHA-256 checksums, signed with the Ed25519 release key below — a key that never touches this web server. A checksum printed on a page the attacker also controls proves nothing, so the signature is the part that matters. Check any download with
Keepsake.exe --verify <file>from a copy you already had installed, or drop it on the verify page. Write the key down once and you can verify every future release by hand, forever, even if this site is gone or lying:3b0e3f9d86279b9aac72bbb497996f5b053f95c62422ab75f00c72598320af76
The update channel uses the same key: the desktop app verifies the signed feed before applying anything, so nobody who controls this server can push code to installed copies. - Reproducible builds. A signature answers “did this file come from Keepsake”. It does not answer “is this file what that source compiles to” — and for a product whose whole claim is that it cannot read your documents, the second question is the one worth asking. Our builds are now deterministic: the same commit, built with the SDK
global.jsonpins, produces byte-identical binaries on any machine and in any directory.pwsh tools/reproduce.ps1is the check — it builds the same commit twice, in two differently named directories, and compares SHA-256 over every file. Two things follow that you can see without our source: the binaries carry no path from our machines (no developer’s home directory inside a file you run), and each release can publish the hash manifest that build produced. Honestly: this applies from the next release onwards. Builds published before 7 September 2026 were made without it, and their binaries do contain build paths. And while the source is not public, this is a command we run and you check the output of — the day the source is available it becomes a command you run. - Authenticated encryption, demonstrated rather than asserted. Every vault in this category prints “authenticated encryption” on its website and almost none of them show you what it buys. Run the experiment:
pwsh tools/compare/tamper.ps1stores the same specimen document twice — once as a Keepsake blob (AES-256-GCM), once in an XTS-AES container of the kind VeraCrypt, BitLocker and LUKS create — then flips one bit at the same place in each and reads both back. Keepsake refuses the document by name and returns nothing at all. The container returns the document, sixteen bytes different, with no error, no warning and no way it could have known.-SelfTestasserts both halves, so if our format ever stopped refusing altered bytes the check would fail rather than the page quietly go on saying this.
Said fairly, because the transcript says it too: this is about detection and nothing else. XTS is not broken and VeraCrypt is not insecure — XTS is length-preserving by design, which is exactly why it has nowhere to put an authentication tag, and that is a trade disk encryption makes on purpose. An attacker who can write to either store still cannot read it and cannot choose what the garbled block becomes. What differs is what happens when nothing catches it.The transcript, as the command printed it (raw)
Keepsake — one bit, flipped in a stored document ================================================= Run: 2026-09-13 11:56:46Z Command: dotnet run --project tools/compare/TamperDemo Document: 144 bytes of specimen passport data SHA-256: c03cb2844e0a04117b90a1275eaf458f22dbba25bce5f1a0ffaa6fb3c3037965 The same document is stored twice: once the way Keepsake stores it, and once the way a disk-encryption container stores it. Then one bit is flipped in each, at the same offset within the encrypted bytes, and each is read back. 1. Keepsake (KVF2 blob: AES-256-GCM, docs/VAULT_FORMAT_V2.md §6) --------------------------------------------------------------- stored 178 bytes (18-byte header + ciphertext + 16-byte tag) read back clean byte for byte identical flipped 1 bit at offset 42, inside the ciphertext read back tampered refused exception VaultTamperException message This file did not pass its authentication check. It is not the file that was stored, or it is being opened with the wrong key. Nothing has been returned from it. bytes returned none 2. A container (XTS-AES-256, the mode VeraCrypt, BitLocker and LUKS use) --------------------------------------------------------------------- stored 144 bytes — exactly the size of the document, which is the point of XTS and the reason it has no room for a tag read back clean byte for byte identical flipped 1 bit at offset 24, the same place in the document read back tampered SUCCEEDED — no error, no warning, no refusal bytes returned 144 bytes changed 16 of 144 (one 16-byte block, garbled) rest of document intact and readable What the reader gets back, first line onward: | PASSPORT (SPECIM···7=m··'··C}D··UM | Given names: SULTANA | Passport no: 533401829 | Date of expiry: 14 AUG 2031 | Issuing authority: HMPO | What this does and does not show -------------------------------- It shows detection, and only detection. An attacker who can write to either store still cannot read it, and cannot choose what the garbled block becomes — XTS gives them sixteen random-looking bytes, not a sentence of their choosing. On a mounted filesystem, a corrupted block is often caught by the filesystem instead. What differs is what happens when nothing catches it. Keepsake refuses the document and says why. The container hands back a document that is sixteen bytes different from the one that was put in, and says nothing, because there is nothing in the format that could have known. Neither behaviour is a bug: XTS is length-preserving on purpose, and a tag will not fit in a design that must not grow. It is a trade, and a vault for documents you will be asked to prove is on the other side of it. VeraCrypt is not insecure, and nothing here suggests it is. It encrypts disks, and this is the property disk encryption gives up to be able to encrypt disks. - Code signing, honestly. Windows installers are not Authenticode-signed yet, so Windows shows an "unrecognised app" warning on first run. We would rather tell you that than have you wonder. The signature scheme above is what protects you in the meantime, and it protects the update channel — which the certificate would not.
- Survivability. If Keepsake disappears tomorrow, the apps keep working, your data stays in your cloud, and the published spec is enough to recover everything.
What this website knows about you
At most: an email address you volunteered, upgrade requests, and Secure Send ciphertext that auto-deletes. No third-party trackers, no ad-tech, no fingerprinting, no cookies on public pages. Details in the privacy policy.
Known past weaknesses (public changelog)
Installs before Vault Format v2 used AES-256-CBC without authentication and direct password-derived file keys. v2 replaced this with authenticated GCM and envelope keys; vaults migrate automatically on first unlock after update. We document this because pretending past versions were perfect is how vendors earn distrust.
Reporting security issues
Email hello@securekeepsake.com. No bug-bounty budget yet — but credited acknowledgements, fast fixes and honest disclosure notes are guaranteed. Please practice coordinated disclosure.
The terms are written down rather than implied: scope, timelines and a safe-harbour commitment are in the vulnerability disclosure policy, and the machine-readable contact is at /.well-known/security.txt (RFC 9116).
Every claim on this page is indexed in the claim ledger, with the command that reproduces it — and the ledger lists what Keepsake does not have in the same table. It is generated, so a number here that stopped matching the artefact it came from would fail the build rather than survive on the page.
What we have not done: commissioned an independent security audit. What stands behind the claims above is a published format you can decrypt a vault from without us, a signed release channel, a reproducible build, and an audit that counts the checks which actually ran rather than the ones we remember writing (pwsh tools/audit/audit.ps1 — the current report is indexed in the ledger), and this page — evidence you can check, not evidence a third party has checked. The distinction is real and we score ourselves down for it on the criteria page.
Last verified — by pwsh tools/audit/audit.ps1. Every claim on this site is listed, with its evidence, in the claim ledger.