1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! Layer 5 — Codex transformation.
//!
//! A [`Codex`] applies a byte-wise transformation to every byte (real key
//! material **and** decoy) before it is stored in fragments. The transformation
//! is an involution: applying it twice returns the original byte. Encoding and
//! decoding therefore call the same operation.
//!
//! # When to use
//!
//! The codex layer is off by default ([`IdentityCodex`]). It is feature-gated
//! behind the `codex` Cargo feature and adds approximately 5–10 ns per byte to
//! the access path. Enabling it raises the work required for an attacker who
//! has already defeated layers 2–4 (mlock, fragmentation, decoy): the bytes
//! they recover are not the bytes the application uses.
//!
//! # Involution requirement
//!
//! All implementations must satisfy `decode(encode(x)) == x` for every byte.
//! This is verified by tests for the built-in codices and, beginning in Phase
//! 0.6, by proptest sweeps over the full byte range.
use PhantomData;
pub use DynamicCodex;
pub use IdentityCodex;
pub use StaticCodex;
/// Byte-wise transformation applied to all stored bytes.
///
/// # Implementor contract
///
/// - **Involution.** For every byte `b`, `self.decode(self.encode(b)) == b`.
/// Equivalently, the transformation is its own inverse.
/// - **Constant-time.** Implementations should be branch-free; the canonical
/// shape is a 256-entry lookup table.
/// - **`Send + Sync`.** Codex instances are shared across threads.
/// Wrap a user-provided closure as a [`Codex`].
///
/// The closure is presumed to be an involution; nothing in the type system
/// enforces this and **violating the property will corrupt every stored key**.
/// Test your closure with the property test in the `codex` integration suite
/// before using it in production.
///
/// # Examples
///
/// ```
/// use key_vault::codex::{Codex, FnCodex};
///
/// // XOR with a fixed mask is an involution.
/// let codex = FnCodex::new(|b: u8| b ^ 0x5a);
/// assert_eq!(codex.decode(codex.encode(0x42)), 0x42);
/// ```