Post-quantum review: hardening and documentation proposals
- Dominant language
- TypeScript
- Stars
- 8
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
## Background
I ran a post-quantum cryptography review of this library (v1.2.3) against current NIST, NSA CNSA 2.0, and OWASP guidance. The top-line finding is that **no PQ algorithm migration is required**: the library is symmetric-only (AES-256-GCM + PBKDF2-HMAC-SHA512 + `crypto.randomBytes`) and has no RSA/ECDH/ECDSA surface, so Shor's algorithm does not apply. Grover's algorithm reduces AES-256 to roughly 128-bit effective security, which both NIST (NISTIR 8105) and NSA CNSA 2.0 consider acceptable against a cryptographically relevant quantum computer.
That said, the review surfaced a small number of classical hardening and documentation items that are worth addressing while the PQ posture is being formally documented. This issue proposes that work.
## Proposed work
### 1. Raise the PBKDF2 iteration count
`KEY_ITERATIONS = 10000` in `src/crypto.ts` is below current OWASP guidance. The 2023 OWASP Password Storage Cheat Sheet recommends a minimum of **210,000 iterations for PBKDF2-HMAC-SHA512** and 600,000 for PBKDF2-HMAC-SHA256. The current value was reasonable when the code was written but has not kept pace with commodity GPU/ASIC throughput. Quantum attackers compound this weakly (Grover gives √iterations), so raising it also incrementally improves the PQ-era margin.
Proposal: raise `KEY_ITERATIONS` to at least 210,000. This is a breaking change for anyone who pins behavior, and per the maintainer note in `README.md` it requires a major version bump. Existing ciphertexts must continue to decrypt (see item 3 below).
### 2. Consider offering a memory-hard KDF alternative
`crypto.scrypt` is in Node core and provides memory-hardness that PBKDF2 does not. Adding it as an opt-in alternative (selected by the stored parameter version, not by caller flag) would future-proof the library against ASIC/FPGA attacks on passphrase-derived keys without changing the public API.
Non-goal: switching the default to scrypt in this release. That can be a follow-up once a parameter-version prefix exists and can be rolled out safely.
### 3. Add a parameter-version prefix to the ciphertext
Today the wire format is `salt || iv || tag || ciphertext`. There is no version byte, so every algorithm or KDF-parameter change is a hard fork of the wire format and has to be managed by callers externally. A single-byte version prefix (`version || salt || iv || tag || ciphertext`) would let us:
- Change `KEY_ITERATIONS`, KDF, or even cipher in future majors without breaking decryption of prior-version ciphertexts.
- Support a formal deprecation window for legacy parameters.
- Keep the README's "later versions can decrypt earlier-version output" promise explicit in the format, not just in code.
This is itself a breaking change to the written format, so it should land together with item 1 in the same major release.
### 4. Backward-compatibility test vectors
The README promises that "all versions of this library are able to decrypt secrets encrypted with previous versions," but the test suite doesn't encode any frozen ciphertexts from prior versions. Before any major bump, add a small set of test vectors — hex-encoded ciphertexts produced by v0.x, v1.0.x, v1.1.x, and v1.2.x — plus a known key/AAD, and assert that the current code still decrypts them. This turns the README promise into a CI-enforced invariant.
### 5. Documentation additions
Add a `SECURITY.md` (or extend the README) that states the following for downstream consumers:
- **PQ posture:** symmetric-only, AES-256-GCM + SHA-512, no asymmetric primitives; aligned with NSA CNSA 2.0 transitional guidance and NIST SP 800-131A Rev. 2.
- **Threat model:** library assumes the caller distributes the passphrase over a PQ-safe channel. Passphrase distribution is out of scope.
- **Grover's caveat:** AES-256 provides ~128-bit post-quantum security. Acceptable per NIST but documented explicitly so consumers can audit their own stacks.
- **Known non-PQ caveat:** current `KEY_ITERATIONS` value (until fixed by this issue) and its implications for offline passphrase attack.
- **Upgrade path:** per-major migration notes, driven by the parameter-version byte from item 3.
### 6. Consumer notification
Primary known consumer is Kibana's encrypted-saved-objects plugin. The major-version bump should be coordinated with that team so they can:
- Pick up the new major in a planned release rather than a Renovate auto-bump.
- Benchmark any bulk re-encrypt code paths (key rotation, saved-object migration tasks) against the new iteration count.
- Confirm in their own release notes that no data re-encryption is required for PQ reasons — existing ciphertexts remain decryptable.
No consumer needs to add PQ-specific code (e.g., ML-KEM / Kyber, ML-DSA / Dilithium). Those become relevant only if this library later grows an asymmetric key-wrapping feature, at which point hybrid KEMs per the IETF hybrid drafts would be the right pattern.
## Out of scope
- Adding asymmetric primitives (RSA, ECDH, signatures). If that ever lands, it is a separate design discussion and should follow FIPS 203 (ML-KEM) / FIPS 204 (ML-DSA) guidance from August 2024.
- Switching the default AEAD. AES-256-GCM remains appropriate; ChaCha20-Poly1305 would be a lateral move, not a security win, on platforms with AES-NI.
## References
- NISTIR 8105, *Report on Post-Quantum Cryptography*
- NIST SP 800-131A Rev. 2, *Transitioning the Use of Cryptographic Algorithms and Key Lengths*
- NSA Commercial National Security Algorithm Suite 2.0 (Sept 2022)
- FIPS 203 (ML-KEM) and FIPS 204 (ML-DSA), finalized August 2024
- OWASP Password Storage Cheat Sheet (2023 revision)
## Suggested sequencing
1. Land test vectors (item 4) on the current minor — non-breaking.
2. Open a v2.0 track covering items 1 and 3 together (iteration bump + version-byte format).
3. Publish the `SECURITY.md` (item 5) alongside v2.0.
4. Evaluate item 2 (scrypt option) as a v2.x minor once the versioned format is in place.
5. Announce to consumers (item 6) when v2.0 is tagged.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.