tasks: decompose vault, core, call crates into 28 atomic implementation tasks
Break down the three initial crates (alknet-vault, alknet-core, alknet-call) into dependency-ordered task files for implementation agents. Structure: - tasks/vault/ (10 tasks) — drift fixes from ADR-025/026 refactor, review, spec sync. Vault is independent and can run fully in parallel with core/call. - tasks/core/ (6 tasks) — crate init, core types, config, auth, endpoint, review. Core is foundational; call depends on it. - tasks/call/ (12 tasks) — split into registry/ and protocol/ topic subdirs reflecting the two subsystems. CallAdapter is the merge point. Key decisions: - Drifts 3+9+10 grouped as one task (key-versioning-rotation) — the complete ADR-021 rotation feature that doesn't compile in pieces - Reviews injected at end of each crate phase (vault, core, call) - Vault spec-sync task removes the drift table and bumps doc status to stable - ACME deferred in core/endpoint (noted as TODO; X509 manual certs for now) - OperationEnv kept as a trait (load-bearing for ADR-024 layering) Validated: 28 tasks, no cycles, 11 generations of parallel work. Critical path runs through call (11 tasks). Vault completes by generation 4. 6 high-risk tasks identified (21%): irpc-removal, endpoint, operation-context, operation-env, call-adapter, abort-cascade.
This commit is contained in:
83
tasks/vault/osrng-iv-generation.md
Normal file
83
tasks/vault/osrng-iv-generation.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: vault/osrng-iv-generation
|
||||
name: Replace rand::random() IV generation with OsRng in AES-GCM encryption
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: medium
|
||||
impact: isolated
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Fix drift item #1: the AES-256-GCM IV (nonce) generation in `encryption.rs`
|
||||
currently uses `rand::random()`, which uses the thread-local RNG and may not be a
|
||||
CSPRNG on all platforms. Replace with `OsRng` (or equivalent CSPRNG).
|
||||
|
||||
This is a security-critical fix. IV reuse under the same AES-GCM key is
|
||||
catastrophic — it breaks authenticity and creates a two-time-pad on the
|
||||
plaintext. `OsRng` reads from the operating system's entropy source and is the
|
||||
correct choice for cryptographic nonces.
|
||||
|
||||
### Current state
|
||||
|
||||
`encryption.rs` line ~133: IV generation uses `rand::random()` to produce the
|
||||
12-byte GCM nonce.
|
||||
|
||||
### Target state
|
||||
|
||||
Use `rand::rngs::OsRng` (from the `rand` crate, which is already a dependency)
|
||||
to generate the 12-byte IV. The `aes-gcm` crate's `Aes256Gcm` encrypt path takes
|
||||
a `Nonce` — construct it from `OsRng`-generated bytes.
|
||||
|
||||
```rust
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
|
||||
let mut iv_bytes = [0u8; 12];
|
||||
OsRng.fill_bytes(&mut iv_bytes);
|
||||
let nonce = Nonce::from_slice(&iv_bytes);
|
||||
```
|
||||
|
||||
The IV is generated fresh for each `encrypt()` call. The salt (32 bytes, unused
|
||||
in v2 for key derivation but kept for wire-format compat) should also use `OsRng`
|
||||
for consistency — it's stored in the `EncryptedData` blob and doesn't need to be
|
||||
deterministic.
|
||||
|
||||
### Scope
|
||||
|
||||
This task touches only `encryption.rs`. It does not depend on the irpc removal
|
||||
(drift #4) because `encryption.rs` is a separate file from `service.rs` /
|
||||
`protocol.rs`. It can run in parallel with drift #4.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `encryption::encrypt()` uses `OsRng` for IV generation, not `rand::random()`
|
||||
- [ ] Salt generation uses `OsRng` (or equivalent CSPRNG)
|
||||
- [ ] No `rand::random()` calls remain in `encryption.rs`
|
||||
- [ ] IV is 12 bytes (standard GCM nonce size)
|
||||
- [ ] Salt is 32 bytes (wire-format compat, unused in key derivation)
|
||||
- [ ] Unit test: verify IV is fresh on each encrypt call (encrypt twice, different IVs)
|
||||
- [ ] Unit test: verify decrypt round-trip still works after the change
|
||||
- [ ] `cargo test` succeeds
|
||||
- [ ] `cargo clippy` succeeds with no warnings
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/crates/vault/README.md — Known Source Drift table item #1
|
||||
- docs/architecture/crates/vault/encryption.md — Security Constraints: OsRng for IVs
|
||||
- docs/architecture/crates/vault/service.md — Security Constraints: OsRng for IVs
|
||||
- docs/architecture/decisions/020-hd-derivation-for-encryption-keys.md — ADR-020
|
||||
|
||||
## Notes
|
||||
|
||||
> This is a security-critical fix. IV reuse under the same AES-GCM key breaks
|
||||
> authenticity and creates a two-time-pad on the plaintext. `rand::random()`
|
||||
> uses the thread-local RNG which may not be a CSPRNG on all platforms; `OsRng`
|
||||
> reads from the operating system's entropy source. This task touches only
|
||||
> `encryption.rs` and can run in parallel with the irpc removal task (drift #4).
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in New Issue
Block a user