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
//! A value that must not outlive its use.
//!
//! # Why `String` is not enough
//!
//! This crate already refuses to let a credential be serialized or printed —
//! [`PeerCredential`](crate::peers::PeerCredential) has no `Serialize` and a
//! redacting `Debug`, and a test scans a real journal for the secret. All of
//! that guards against a secret being *written somewhere*.
//!
//! None of it guards against the secret simply **staying in memory**. A `String`
//! dropped is a `String` freed, and freed heap keeps its bytes until something
//! else claims the page — where a core dump, a swap file, or a heap-reading
//! exploit finds them. Worse, `String` reallocates as it grows, so an unlucky
//! construction leaves *several* copies behind, none of which the eventual drop
//! can reach.
//!
//! [`Secret`] closes that: the bytes are wiped when it drops, and every copy
//! wipes its own.
//!
//! # What it cannot do
//!
//! It cannot reach a secret that existed before it. A key read from an
//! environment variable was already copied into the process by the loader; one
//! built with `format!` left an intermediate buffer. `Secret` bounds the
//! lifetime of *its* copy, which is the copy this crate is responsible for.
use fmt;
use Zeroizing;
/// A secret that is wiped when it drops.
///
/// Deliberately missing: `Serialize`, `Deserialize`, and any `Display` that
/// reveals the value. The only way out is [`expose`](Self::expose), which is
/// greppable — an audit for "where does this secret go" is a search for one
/// method name.
;
/// Comparison is constant-time in the length of the shorter value.
///
/// A bearer token compared with `==` leaks its prefix through timing: an
/// attacker who can measure the comparison learns how many leading bytes they
/// guessed correctly. That is a real attack on any code path where an attacker
/// controls one side, and cheap enough to avoid that there is no reason to
/// reason about which paths those are.
/// Compare without short-circuiting on the first differing byte.
///
/// One implementation, because this is the whole of the defence: a secret or a
/// MAC compared with `==` leaks how many leading bytes the caller guessed,
/// which turns a forgery from infeasible into a byte-at-a-time search. A second
/// copy is a second thing to get right, and the one that is wrong is the one
/// nobody looked at.
///
/// Length is not secret — it is fixed by the scheme and visible through the
/// ciphertext of any transport — but the contents must not short-circuit.
pub