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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
use ;
use StrongBox;
use ;
/// A way to derive many [`StrongBox`]es from one set of keys.
///
/// Splitting different encryption usages to use different keys prevents accidental misuse,
/// and reduces the chances of insecurity from overuse. Rather than have to manage a whole
/// bunch of keys, though, a [`StemStrongBox`] allows you to "derive" [`StrongBox`]es for
/// different uses from a single "root" [`StemStrongBox`].
///
/// Let us say, for instance, that you have a typical web application. You want to keep
/// session data in cookies, but that needs to be encrypted to prevent disclosure and
/// tampering. You also have to encrypt the state data that you send to your OAuth providers,
/// and you have a couple of database fields that are *super* sensitive, that you'd like to
/// encrypt.
///
/// Traditionally, you'd need to have a set of keys for each of those uses -- which is an absolute pain.
/// However, with the [`StemStrongBox`], you only need to manage one set of keys (the current
/// encryption key, and any previous decryption keys that old data might still be encrypted
/// under), and the other keys can all be *derived* from that one "root" set of keys.
///
/// We might have a "key hierarchy" that looks something like this:
///
/// ```text
/// +--------+
/// | root |
/// +--------+
/// / | \
/// / | \
/// / | \
/// / | \
/// / | \
/// +=========+ +-------+ +=========+
/// | cookies | | DB | | OAuth |
/// +=========+ +-------+ +=========+
/// / \
/// / \
/// / \
/// / \
/// +----------+ +-----------+
/// | table1 | | table2 |
/// +----------+ +-----------+
/// / / \
/// / / \
/// / / \
/// / / \
/// +===========+ +===========+ +===========+
/// | sensitive | | sensitive | | sensitive |
/// | column A | | column B | | column C |
/// +===========+ +===========+ +===========+
/// ```
///
/// In the above diagram, the boxes with `---` at top and bottom are [`StemStrongBox`]es, from
/// which you can derive other StrongBoxes (any of [`StemStrongBox`], [`StaticStrongBox`], or [``RotatingStrongBox`]).
/// The boxes with `===` at top and bottom are regular [`StrongBox`]es, and are the ones we use to
/// do cryptography.
///
/// You deliberately cannot have a kind of [`StrongBox`] that can both perform encryption and key
/// derivation, because it is a terrible idea, security wise, to use the same key for different
/// purposes. Through the power of Rust's type system, we can enforce that.
///
/// # Example
///
/// This is how you might setup the above "tree" of [`StrongBox`]es.
///
/// ```rust
/// # use strong_box::{Error, StemStrongBox};
/// # use std::time::Duration;
/// # fn main() -> Result<(), Error> {
/// # const WEEKLY: Duration = Duration::from_secs(7 * 24 * 3600);
///
/// // A couple of keys are always useful to have
/// let old_key = strong_box::generate_key();
/// let new_key = strong_box::generate_key();
///
/// // This is the basis of all our other boxes
/// let root = StemStrongBox::new(new_key.clone(), [old_key, new_key]);
///
/// // This creates a RotatingStrongBox for secure cookie storage
/// let cookies = root.derive_rotating("cookies", WEEKLY, 52);
///
/// // This is the OAuth provider state box
/// let oauth = root.derive_static("OAuth");
///
/// // Then the great tree of DB column encryption boxes
/// let db = root.derive_stem("DB");
/// let table1 = db.derive_stem("table1");
/// let table2 = db.derive_stem("table2");
///
/// let sensitive_column_a = table1.derive_static("sensitive column A");
/// let sensitive_column_b = table2.derive_static("sensitive column B");
/// let sensitive_column_c = table2.derive_static("sensitive column C");
///
/// // We can now call encrypt/decrypt on any of the boxes created by .derive or .derive_rotating, but
/// // not any of the boxes created by derive_stem, as they are only for further derivation
/// # Ok(())
/// # }
/// ```