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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
use fmt;
/// A passphrase for password‑based encryption and decryption.
///
/// # Purpose
///
/// `Passphrase` wraps a secret string (the passphrase) and ensures that it is:
/// - **Erased from memory** when no longer needed (via a custom [`Drop`]).
/// - **Redacted** in debug and display output to prevent accidental exposure.
///
/// This follows the principle of least privilege for secrets: the plaintext
/// passphrase lives in memory for the shortest possible time and is never
/// accidentally logged.
///
/// # Construction
///
/// Use [`Passphrase::new`] to create an instance from a `&str`. The
/// constructor copies the bytes into a heap‑allocated buffer (`Vec<u8>`)
/// that we control.
///
/// # Accessing the passphrase
///
/// The only way to access the contents is [`expose`](Passphrase::expose),
/// which returns a `&str`. This method is intentionally named `expose` to
/// make it obvious that you are revealing the secret.
///
/// # Memory clearing
///
/// When a `Passphrase` is dropped, the [`Drop`] implementation:
/// 1. Writes `0` to every byte of the internal buffer using
/// [`std::ptr::write_volatile`] to prevent the compiler from optimizing
/// away the write (it is not a “dead store”).
/// 2. Emits a **sequential consistency memory fence** via
/// [`std::sync::atomic::fence`] to ensure the zeroing is visible to
/// all threads and not reordered.
///
/// This makes it much harder for an attacker with access to memory dumps
/// to recover the passphrase after the `Passphrase` has been dropped.
///
/// # Cloning
///
/// `Passphrase` implements [`Clone`]. Cloning creates a **new copy** of
/// the secret in memory. Both the original and the clone will be zeroed
/// independently when they are dropped. Avoid unnecessary cloning to
/// reduce the number of copies of the secret in memory.
///
/// # Examples
///
/// ```ignore
/// use age_crypto::types::Passphrase;
///
/// let pass = Passphrase::new("my-secret-password");
/// let plaintext = pass.expose(); // use for encryption/decryption
/// assert_eq!(plaintext, "my-secret-password");
/// // pass is dropped here → memory zeroed
/// ```
/// **Security‑critical drop implementation.**
///
/// When a `Passphrase` goes out of scope, its byte buffer is overwritten
/// with zeros to reduce the window of memory exposure. The use of
/// `write_volatile` and a memory fence helps ensure the clearing is not
/// optimized away by the compiler and is visible to all execution threads.
///
/// # Important
///
/// - This does **not** scrub other copies of the passphrase that may exist
/// in strings or other buffers. The caller is responsible for managing
/// those.
/// - The clearing happens *before* deallocation, but after zeroing the
/// memory is still part of the allocation and could theoretically be
/// swapped to disk or read by another process with sufficient privileges.
/// For the highest security, use [`secrecy::SecretVec`] or similar
/// dedicated types.
/// Cloning a `Passphrase` duplicates the secret into a new buffer.
///
/// Both the clone and the original will be independently zeroed when
/// dropped. Be mindful that this increases the number of copies of the
/// secret in memory; clone only when absolutely necessary.
/// Debug formatting that **never** reveals the passphrase.
///
/// The output shows only the length of the passphrase and a `[REDACTED]`
/// placeholder. This makes it safe to include `Passphrase` in structs
/// that derive `Debug` without accidentally logging the secret.
/// Display that **never** reveals the passphrase.
///
/// Any attempt to format a `Passphrase` with `{}` will produce the
/// constant string `[REDACTED]`. This prevents accidental exposure in
/// user‑facing messages or logs.