chronogrid/docs/ARCHITECTURE/ADR/0002-crypto-argon2id-keycha...

43 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-0002: chronogrid_crypto – Argon2id KDF & OS Keychain Strategy
* **Status**: Accepted
* **Date**: 2026-08-09
* **Deciders**: Michael Kell
## Context & Problem Statement
Task 1.2 requires implementing a `chronogrid_crypto` crate that provides:
1. A master-key derivation function using Argon2id with parameters mandated by `docs/ARCHITECTURE/02-security-and-crypto.md`.
2. Cross-platform OS keychain bindings for secure credential persistence (Windows, Linux). Android is deferred to the Flutter KeyStore bridge.
## Options Considered
1. **Hand-roll Argon2id via raw `blake2` + memory-hard loop** — maximum control but high risk of implementation bugs in a security-critical path.
2. **Use the `argon2` crate (RustCrypto)** — well-audited, widely used, supports Argon2id with configurable parameters out of the box.
3. **Use `ring` or `sodiumoxide`** — neither provides Argon2id natively; would still need the `argon2` crate.
For keychain:
1. **Direct Win32 / libsecret FFI** — full control, but significant per-platform maintenance burden.
2. **`keyring` crate** — abstracts Windows Credential Manager, Linux SecretService, and macOS Keychain behind a single API.
## Decision Outcome
**Chosen Options:**
* `argon2` crate v0.5 (RustCrypto) for KDF — spec-compliant, zero-copy output, and widely audited.
* `keyring` crate v3 for cross-platform OS keychain — minimal code, covers Windows + Linux targets. Android is excluded via `cfg(not(target_os = "android"))` and will be handled by the Flutter KeyStore bridge.
**Key design choices:**
* Argon2id parameters: memory = 65 536 KiB (64 MiB), time_cost = 3, parallelism = 4, salt = 16 bytes, output = 32 bytes.
* `DerivedKey` struct wraps key + salt and implements `Zeroize + Drop` for automatic memory scrubbing.
* `Debug` impl on `DerivedKey` redacts key material to prevent accidental log leaks.
* Raw bytes are Base64-encoded before keychain insertion for UTF-8 credential backend compatibility, using inline encode/decode helpers (no extra dependency).
## Consequences & Trade-offs
* **Positive**: Spec-compliant crypto with secure memory handling; single cross-platform keychain API; 8 unit tests + 1 doc-test provide baseline confidence.
* **Negative**: `keyring` v3 does not support Android — Android keychain must be wired separately via Flutter platform channels (planned for Task 1.5). Inline Base64 is minimal but could be replaced by `base64` crate if other crates need it later.