Commit 597dd7f
docs(vault): v3 KDF-stretch design spec (scrypt)
Read-only design pass. NO source code changes. The deliverable is a
723-line spec at docs/superpowers/specs/ that the user reviews before
implementation runs in a future session.
Vault v2 (commit 8511569) randomized the HKDF salt per-vault/per-write
but kept HKDF-SHA256 as the KDF -- which has NO password-stretching
work factor. Weak passphrases remain feasible to brute-force even
with a random salt. Vault v3 adds a true password KDF.
Spec recommends: scrypt (node:crypto built-in). Rationale:
- Zero new dependency, no native build, no Windows install-tools
risk, no extra tsup external, no prepare-package-deps.mjs change.
- Linux passphrase users (the highest-friction case per
linux/perplexity-codex-mcp-setup-issue.md, addressed in commit
7a9f36c) get the security upgrade with no install risk.
- Recommended params logN=17, r=8, p=1, maxmem=256MiB give ~300ms
one-shot cost on a 2020 laptop, ~128 MiB peak memory.
- Format reserves KDF_ID = 0x02 for argon2id so a future swap is
a clean dispatch-table extension, not a format-version bump.
File format v3 byte layout:
[MAGIC 4][VERSION 0x03][KDF_ID 1][KDF_PARAMS_LEN 1][KDF_PARAMS n]
[SALT_LEN 1][SALT 16][IV 12][CIPHERTEXT m][AUTHTAG 16]
Migration story: v1 and v2 stay readable forever (decrypt-only); all
NEW writes emit v3 with the new KDF + fresh salt + current params;
opportunistic migration on next legitimate Vault.set after v1 or v2
read. Keychain users unaffected (32-byte random key bypasses HKDF).
Public API impact: encryptBlob / decryptBlob / getMasterKey /
getUnsealmaterial signatures all preserved. New internal helper
deriveKeyForVersion(unseal, version, salt, kdfParams) -> Buffer.
4 open questions for the user to resolve before implementation:
Q1: scrypt vs argon2id (recommended scrypt -- Node built-in, no
native build issues; argon2id is theoretically stronger but
adds a dep).
Q2: test-mode KDF override mechanism (env-var vs module seam --
lean module seam).
Q3: logN=17 vs logN=18 startup cost trade-off (recommend 17 with
annual re-tune).
Q4: document v4 per-profile keys as a future non-goal (recommend
yes, mention only).
The spec lives under docs/ which is gitignored (.gitignore:66) and
was force-added (git add -f) per the post-public-repo workflow that
keeps .gitignore unchanged but allows narrow per-file inclusion.
This puts the design into the public-repo review trail.
Implementation is OUT OF SCOPE for this commit. Future task:
~2 commits per the spec's implementation plan, modifies vault.js
+ vault.d.ts + vault.test.js only. No callers outside vault need
to change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 256589b commit 597dd7f
1 file changed
Lines changed: 723 additions & 0 deletions
0 commit comments