--- phase: 12-user-key-input plan: 02 subsystem: crypto tags: [argon2id, rpassword, kdf, salt, password-authentication] # Dependency graph requires: - phase: 12-user-key-input plan: 01 provides: "CLI --key/--key-file key input, KeySource enum, resolve_key()" provides: - "Full --password support with Argon2id KDF and 16-byte random salt" - "Salt storage in archive format (flags bit 4, 16 bytes between header and TOC)" - "Interactive password prompt via rpassword with confirmation on pack" - "resolve_key_for_pack() and resolve_key_for_unpack() two-phase API" affects: [kotlin-decoder, format-spec] # Tech tracking tech-stack: added: [argon2 0.5, rpassword 7.4] patterns: [two-phase key resolution for password (salt lifecycle), flags-based optional format sections] key-files: created: [] modified: - Cargo.toml - src/key.rs - src/format.rs - src/archive.rs - src/main.rs - tests/round_trip.rs key-decisions: - "Two-phase key resolution: resolve_key_for_pack() generates salt, resolve_key_for_unpack() reads salt from archive" - "Salt stored as 16 plaintext bytes between header (offset 40) and TOC (offset 56) when flags bit 4 set" - "Argon2id with default parameters (Argon2::default()) for key derivation" - "pack prompts for password confirmation (enter twice), unpack prompts once" patterns-established: - "Flags-based optional format sections: bit 4 signals 16-byte salt between header and TOC" - "Two-phase key resolution pattern: pack generates salt, unpack reads salt then derives key" requirements-completed: [KEY-03, KEY-04, KEY-05, KEY-06] # Metrics duration: 5min completed: 2026-02-26 --- # Phase 12 Plan 02: Password-Based Key Derivation Summary **Argon2id KDF with 16-byte random salt stored in archive format, completing --password support via rpassword interactive prompt** ## Performance - **Duration:** 5 min - **Started:** 2026-02-26T20:56:34Z - **Completed:** 2026-02-26T21:01:33Z - **Tasks:** 2 - **Files modified:** 6 ## Accomplishments - Argon2id KDF derives 32-byte key from password + 16-byte random salt using argon2 crate - Archives created with --password store salt in format (flags bit 4, 16 bytes at offset 40-55, TOC at 56) - All three key input methods (--key, --key-file, --password) fully functional end-to-end - Wrong password correctly rejected via HMAC/decryption failure - All 52 tests pass: 25 unit + 7 golden + 20 integration (5 new password tests added) ## Task Commits Each task was committed atomically: 1. **Task 1: Implement Argon2id KDF, rpassword prompt, and salt format** - `035879b` (feat) 2. **Task 2: Wire salt into archive pack/unpack, update main.rs, and add tests** - `4077847` (feat) ## Files Created/Modified - `Cargo.toml` - Added argon2 0.5 and rpassword 7.4 dependencies - `src/key.rs` - derive_key_from_password(), prompt_password(), resolve_key_for_pack/unpack(), ResolvedKey struct - `src/format.rs` - FLAG_KDF_SALT, SALT_SIZE constants, read_salt/write_salt functions, relaxed flags validation - `src/archive.rs` - Pack accepts optional salt, read_archive_metadata returns salt, read_archive_salt() helper - `src/main.rs` - Two-phase password key resolution for pack/unpack/inspect - `tests/round_trip.rs` - 5 new tests: password roundtrip, wrong password, salt flag, no-salt flag, directory password ## Decisions Made - Two-phase key resolution API: resolve_key_for_pack() generates random salt and returns ResolvedKey with key+salt; resolve_key_for_unpack() reads salt from archive before deriving key - Salt is 16 bytes of plaintext between header and TOC (not encrypted), signaled by flags bit 4 (0x10) - Argon2id with default parameters (19 MiB memory, 2 iterations, 1 parallelism) for key derivation - Pack prompts password twice (confirmation), unpack prompts once - Legacy resolve_key() kept for inspect keyless path (errors on password variant) ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - All three key input methods complete: --key (hex), --key-file (raw bytes), --password (Argon2id) - Phase 12 is now complete - all user key input requirements fulfilled - Future work: Kotlin decoder may need password/salt support for interop ## Self-Check: PASSED All 6 modified files verified present. Both task commits (035879b, 4077847) found in git log. --- *Phase: 12-user-key-input* *Completed: 2026-02-26*