Files
alknet/tasks/vault/osrng-iv-generation.md
glm-5.2 098fd8b9b9 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.
2026-06-23 12:41:47 +00:00

3.0 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
vault/osrng-iv-generation Replace rand::random() IV generation with OsRng in AES-GCM encryption pending
single medium isolated 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.

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