key-vault 0.7.0

Enterprise-grade key management vault for Rust. 9-layer defense-in-depth: fragmentation, decoy bytes, codex transform, mlock + zeroize, constant-time ops, security monitoring. Pluggable key fetchers (TPM, keychain, file, env). Sub-microsecond access. REPS-compliant.
Documentation
<h1 align="center">
    <img width="99" alt="Rust logo" src="https://raw.githubusercontent.com/jamesgober/rust-collection/72baabd71f00e14aa9184efcb16fa3deddda3a0a/assets/rust-logo.svg">
    <br>
    <b>key-vault</b>
    <br>
    <sub>
        <sup>ENTERPRISE-GRADE KEY MANAGEMENT VAULT</sup>
    </sub>
</h1>

<p align="center">
    <a href="https://crates.io/crates/key-vault"><img src="https://img.shields.io/crates/v/key-vault.svg" alt="Crates.io"></a>
    <a href="https://crates.io/crates/key-vault"><img alt="downloads" src="https://img.shields.io/crates/d/key-vault?color=%230099ff"></a>
    <a href="https://docs.rs/key-vault"><img src="https://docs.rs/key-vault/badge.svg" alt="Documentation"></a>
    <a href="https://github.com/jamesgober/key-vault/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/jamesgober/key-vault/actions/workflows/ci.yml/badge.svg"></a>
    <a href="https://github.com/rust-lang/rfcs/blob/master/text/2495-min-rust-version.md" title="MSRV"><img alt="MSRV" src="https://img.shields.io/badge/MSRV-1.85%2B-blue"></a>
</p>

<p align="center">
    <b>9-Layer Defense-in-Depth In-Memory Key Storage for Rust</b>
    <br>
    <i>Fragmentation + decoy bytes + codex transform + mlock + zeroize + constant-time + monitoring + audit + page protection.</i>
</p>

<br>

<p>
    <strong>key-vault</strong> is an enterprise-grade key management vault built to keep cryptographic key material safe in memory while your application is running. Built from the ground up with a <b>9-layer defense-in-depth philosophy</b>, it combines hardware-rooted acquisition, memory page locking, fragmentation with self-referential decoy bytes, codex transformation, zero-on-drop, constant-time operations, security event monitoring, and audit logging to make memory-resident keys hard to extract via memory analysis, scraping, or forensic recovery.
</p>

<p>
    Unlike libraries that hand you a <code>Vec&lt;u8&gt;</code> and trust you not to leak it, <strong>key-vault</strong> wraps key material in opaque <code>KeyHandle</code> references. The actual bytes never live contiguously in memory after the vault initializes; they're split into variable-size fragments scattered across non-contiguous mlock'd allocations, interleaved with self-referential decoy bytes that statistically match the key's entropy profile, optionally transformed through a codex layer, and reassembled only when explicitly requested in protected scopes. The temporary contiguous copy auto-zeroizes when dropped.
</p>

<p>
    <strong>key-vault</strong> ships with multiple <b>fragment strategies</b> (standard, interleaved, random, layered composition), <b>decoy strategies</b> (random, self-referential, key-derived), pluggable <b>key fetchers</b> (TPM 2.0 hardware, OS keychains, encrypted files, environment variables), and an <b>extensible security monitor</b> for failure detection and anomaly alerting. Master key recovery, atomic key rotation, multi-key vaults, and <b>TEE detection</b> are built in. <b>Post-quantum</b> safe symmetric defaults (256-bit minimum) future-proof you against the next decade of cryptographic landscape changes.
</p>

---

## 9-Layer Defense Architecture

The complete defense stack:

| Layer | Defense | Defends Against |
|-------|---------|-----------------|
| **1** | **Secure Acquisition** (TPM, Keychain, etc.) | Untrusted key sources |
| **2** | **Memory Page Locking** (mlock / VirtualLock) | Swap files, hibernation |
| **3** | **Fragment Strategy** (variable chunks, shuffle) | Pattern recognition, memory scraping |
| **4** | **Decoy Bytes** (self-referential filler) | Entropy/frequency analysis |
| **5** | **Codex Transformation** (byte swap) | Memory dump analysis |
| **6** | **Constant-Time Operations** | Timing side-channels |
| **7** | **Zero-On-Drop** | Use-after-free leakage |
| **8** | **Security Monitor** (failure detection) | Brute-force, anomalous access |
| **9** | **Audit Logging** | Forensic trail, compliance |
| **10** | (Bonus) Page Protection Toggling | Snapshot attacks |

**Full details:** see [docs/SECURITY.md](docs/SECURITY.md) for the comprehensive security architecture.

**Visual walkthrough:** see [docs/TRANSFORMATION.md](docs/TRANSFORMATION.md) for a step-by-step trace of what happens to a key as it passes through all the layers.

---

## Current status

**`key-vault` is pre-1.0; the public API is not yet stable.** The 9-layer
architecture above is the **1.0 design target**. Each release lights up more
of it. The "Features" section below documents the 1.0 surface; the table here
records what is actually built today so you can match the README against the
shipped code.

| Component | Status as of 0.7.0 |
|-----------|--------------------|
| Public type system (`Error`, `Result`, `KeyHandle`, `KeyMetadata`, `RawKey`, `FetchContext`, `Fragments`) | shipped |
| Trait surfaces (`KeyFetch`, `FragmentStrategy`, `DecoyStrategy`, `Codex`, `SecurityMonitor`) | shipped |
| **Layer 2 — mlock / VirtualLock** (via internal `LockedBytes` wrapper) | shipped |
| **Layer 3 — All four fragment strategies**: `StandardFragmenter`, `RandomFragmenter`, `InterleavedFragmenter`, `LayeredFragmenter` | shipped |
| **Layer 4 — Decoy strategies** (`RandomDecoy`, `SelfReferenceDecoy`, `KeyDerivedDecoy`) | shipped |
| **Layer 5 — Full codex stack**: `IdentityCodex`, `FnCodex`, `StaticCodex`, `DynamicCodex` (table in `LockedBytes`) | **shipped** |
| **Layer 6 — Constant-time `KeyHandle` equality** (via `subtle::ConstantTimeEq`) | shipped |
| **Layer 7 — Zero-on-drop** (every fragment + layout buffer + intermediate plaintext + decoy buffer + codex table) | shipped |
| BLAKE3 key normalization (wired through `KeyVaultBuilder::normalize_with_blake3`) | shipped |
| TEE detection (`detect_tee_capabilities`) | shipped (real x86_64 + Apple SE + AWS Nitro probes) |
| `KeyVault::fragment` / `KeyVault::defragment` convenience methods | shipped (uses `StandardFragmenter` internally) |
| `KeyVaultBuilder::with_chunk_range` / `with_decoy` / `with_codex` | shipped |
| **Layer 1 — built-in fetchers** (`EnvFetch`, `FileFetch`, `KeychainFetch`, `TpmFetch` detection) | **shipped** |
| Layer 8 — Monitor implementations | planned for 0.8.0 |
| Layer 9 — Audit logging | planned for 0.8.0 |
| Multi-key vaults, rotation, master recovery | planned for 0.9.0 |
| Criterion benchmark suite | planned for 0.10.0 |

Each phase's exit criteria, scope, and timeline are tracked in
[.dev/ROADMAP.md](.dev/ROADMAP.md).

---

## Features (the 1.0 design)

### Defense-in-depth memory protection (1.0 design)

- **Memory page locking** (mlock / VirtualLock) prevents key material from being swapped to disk
- **Fragment storage** splits keys into variable-sized chunks at non-contiguous addresses
- **Self-referential decoy bytes** statistically indistinguishable from real key material
- **Codex transformation** (opt-in) adds byte-level obfuscation
- **Zero-on-drop** via zeroize overwrites memory when keys leave scope
- **Constant-time comparisons** via subtle prevent timing attacks
- **No debug exposure** — `KeyHandle`'s `Debug` impl always prints `KeyHandle(<redacted>)` (shipped today)

### Pluggable key fetchers (all four shipped in 0.7.0)

- **`TpmFetch`** — detection-only in 1.0, full integration deferred to 1.x (feature `fetcher-tpm`)
- **`KeychainFetch`** — macOS Keychain, Windows Credential Manager, Linux Secret Service via the `keyring` crate (feature `fetcher-keychain`)
- **`FileFetch`** — file-on-disk with strict Unix permission checks (`0o600`) (feature `fetcher-file`)
- **`EnvFetch`** — process environment variable, error messages never log the value (feature `fetcher-env`)
- **Custom fetchers** via the `KeyFetch` trait — bring your own HSM, KMS client, or proprietary source

### Fragment strategies (all four shipped in 0.5.0)

- **Standard** — variable chunks + Fisher-Yates shuffle, each chunk in its own mlock'd allocation
- **Random** — chunks of variable size whose bytes come from **non-contiguous** positions in the key (no chunk holds a contiguous key substring longer than 1)
- **Interleaved** — single large pool, key bytes scattered at random positions, gaps filled with CSPRNG padding
- **Layered** — routes each fragmentation to a uniformly-picked sub-strategy; strategy index encoded in the layout header so defragment dispatches correctly
- **Custom** — implement the `FragmentStrategy` trait

See [docs/SECURITY.md](docs/SECURITY.md#strategies-shipped-in-050) for the
per-strategy threat-model comparison.

### Decoy strategies (1.0 design, `DecoyStrategy` trait shipped)

- **Random** — raw RNG bytes (fastest, weakest) — **shipped in 0.4.0**
- **Self-Reference** — real key bytes used as filler (strongest, recommended default) — **shipped in 0.4.0**
- **Key-Derived** — BLAKE3-XOF bytes seeded by key + per-call nonce — **shipped in 0.4.0**

### Codex layer (Layer 5, all four shipped in 0.6.0)

- **`IdentityCodex`** — no transformation (default, max performance) — shipped in 0.2.0
- **`FnCodex`** — user-provided closure (involution-only) — shipped in 0.2.0
- **`StaticCodex`** — declarative swap table (`from_swaps(&[(u8, u8)])`) or fresh random involution (`random_involution()`) — **shipped in 0.6.0**
- **`DynamicCodex`** — per-vault randomized involution with no fixed points — **shipped in 0.6.0**

All codex tables live in `LockedBytes` (mlock'd, zeroed on drop).
Encoding/decoding is one memory load per byte (constant-time, branch-free).

### Security monitoring (Layer 8, trait shipped)

- **Failed decryption detection** — N failures in M seconds triggers configurable response — 0.8.0
- **Anomalous access patterns** — detect sustained data exfiltration — 0.8.0
- **Threshold lockout** — lock vault after threshold breach — 0.8.0
- **Pluggable sinks** — log, metrics, webhook, custom — 0.8.0

### Operational features

- **Master key recovery** — fallback path for hardware failure — 0.9.0
- **Key rotation** — atomic swap to new key without dropping access — 0.9.0
- **Multiple keys per vault** — named keys with independent lifecycles — 0.9.0
- **TEE detection** — check for Intel SGX, Intel TDX, AMD SEV, AMD SEV-SNP, ARM TrustZone, Apple Secure Enclave, AWS Nitro — **shipped**
- **Key normalization** — BLAKE3 hash input to neutralize format-based pattern leaks — **shipped in 0.3.0**

### Performance targets (1.0 design — not yet measured)

- **Key acquisition** — sub-second from hardware, sub-millisecond from keychain
- **Key access** (defrag into temporary buffer) — sub-microsecond (~500ns including audit + monitor)
- **Concurrent access** — lock-free reads after vault initialization
- **Memory overhead** — < 16 KiB per key (including fragment + decoy overhead)
- **Zero allocations** on the hot path (after vault initialization)

> **Note on benchmark numbers:** detailed criterion-backed benchmark numbers will land with **v1.0.0** (Phase 0.10.0 in the roadmap). Until then, performance numbers are targets, not measurements.

---

## Quick start

```toml
[dependencies]
key-vault = "0.7"
```

```rust
use key_vault::{DynamicCodex, KeyVaultBuilder, RawKey, SelfReferenceDecoy};
use key_vault::tee::detect_tee_capabilities;

// Build a vault with the full default stack: Layer 2 (mlock/VirtualLock)
// + Layer 3 (StandardFragmenter) + Layer 4 (SelfReferenceDecoy — the
// strongest decoy) + Layer 5 (per-vault DynamicCodex involution)
// + Layer 6 (ConstantTimeEq) + Layer 7 (zero-on-drop).
let vault = KeyVaultBuilder::new()
    .normalize_with_blake3(true) // default
    .with_codex(DynamicCodex::new().expect("codex"))
    .with_decoy(SelfReferenceDecoy)
    .build();

// Hand the vault some key material and get back an opaque, scattered,
// mlock'd, zeroed-on-drop representation with decoy chunks mixed in.
let raw = RawKey::new(b"my application key".to_vec());
let frags = vault.fragment(&raw).expect("fragment");

// Reassemble when you need to use it. With BLAKE3 normalization on,
// the recovered bytes are the 32-byte hash of the input.
let recovered = vault.defragment(&frags).expect("defragment");
assert_eq!(recovered.len(), 32);

// Snapshot the host's TEE capabilities at startup:
let caps = detect_tee_capabilities();
println!("{caps}");
```

---

## Threat model

key-vault is designed to defend against:

- **Memory scraping by attackers with read access** — malware, forensic tools
- **Forensic memory analysis** — swap files, hibernation files, crash dumps
- **Statistical pattern recognition** — entropy analysis, frequency analysis
- **Use-after-free leakage** — keys persisting after they should have been wiped
- **Brute-force decryption attempts** — failed attempts trigger alerts
- **Timing side-channels** — constant-time operations
- **Insider threats / forensic compliance** — full audit trail

It does NOT defend against:

- **Code execution within your process** — an attacker who can call your reassembly logic
- **Hardware-level memory access (DMA attacks)** — use IOMMU + hardware mitigations
- **Cold-boot attacks** — use full disk encryption + power-down protocol
- **Side-channel attacks on cryptographic operations** — that's crypt-io's job
- **Quantum computer attacks on asymmetric crypto** — use post-quantum algorithms (symmetric defaults are PQ-safe)

See [docs/SECURITY.md](docs/SECURITY.md) for the full threat model.

---

## Documentation

- **[docs/API.md](docs/API.md)** — Full public-API reference (every type, function, and method with examples)
- **[docs/SECURITY.md](docs/SECURITY.md)** — Comprehensive 9-layer security architecture
- **[docs/TRANSFORMATION.md](docs/TRANSFORMATION.md)** — Visual walkthrough of key transformation
- **[docs/release/](docs/release/)** — Per-version release notes
- **[CHANGELOG.md](CHANGELOG.md)** — Full change log (Keep a Changelog format)

---

## Standards

- **REPS** (Rust Efficiency & Performance Standards) governs every decision. See [REPS.md](REPS.md).
- **MSRV:** Rust 1.85.
- **Edition:** 2024.
- **Cross-platform:** Linux, macOS, Windows.

---

## License

Dual-licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT License ([LICENSE-MIT](LICENSE-MIT))

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.



<!-- FOOT COPYRIGHT
################################################# -->
<div align="center">
  <h2></h2>
  <sup>COPYRIGHT <small>&copy;</small> 2026 <strong>JAMES GOBER.</strong></sup>
</div>