askar_crypto/buffer/
secret.rs1use alloc::{boxed::Box, string::String, vec::Vec};
2use core::{
3 fmt::{self, Debug, Formatter},
4 hash, mem,
5 ops::{Deref, Range},
6};
7
8use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
9use subtle::{Choice, ConstantTimeEq};
10use zeroize::Zeroize;
11
12use super::{string::MaybeStr, HexRepr, ResizeBuffer, WriteBuffer};
13use crate::error::Error;
14
15#[derive(Clone, Default, Zeroize)]
17pub struct SecretBytes(Vec<u8>);
18
19impl SecretBytes {
20 pub fn new_with(len: usize, f: impl FnOnce(&mut [u8])) -> Self {
22 let mut slf = Self::with_capacity(len);
23 slf.0.resize(len, 0u8);
24 f(slf.0.as_mut());
25 slf
26 }
27
28 #[inline]
30 pub fn with_capacity(max_len: usize) -> Self {
31 Self(Vec::with_capacity(max_len))
32 }
33
34 #[inline]
36 pub fn from_slice(data: &[u8]) -> Self {
37 let mut v = Vec::with_capacity(data.len());
38 v.extend_from_slice(data);
39 Self(v)
40 }
41
42 #[inline]
44 pub fn from_slice_reserve(data: &[u8], reserve: usize) -> Self {
45 let mut v = Vec::with_capacity(data.len() + reserve);
46 v.extend_from_slice(data);
47 Self(v)
48 }
49
50 #[inline]
52 pub fn capacity(&self) -> usize {
53 self.0.capacity()
54 }
55
56 #[inline]
58 pub fn len(&self) -> usize {
59 self.0.len()
60 }
61
62 #[inline]
64 pub fn is_empty(&self) -> bool {
65 self.0.is_empty()
66 }
67
68 pub fn as_opt_str(&self) -> Option<&str> {
70 core::str::from_utf8(self.0.as_slice()).ok()
71 }
72
73 pub fn ensure_capacity(&mut self, min_cap: usize) {
75 let cap = self.0.capacity();
76 if cap == 0 {
77 self.0.reserve(min_cap);
78 } else if cap > 0 && min_cap >= cap {
79 let new_cap = min_cap.max(cap * 2).max(32);
81 let mut buf = Self::with_capacity(new_cap);
82 buf.0.extend_from_slice(&self.0[..]);
83 mem::swap(&mut buf, self);
84 }
86 }
87
88 #[inline]
90 pub fn extend_from_slice(&mut self, data: &[u8]) {
91 self.reserve(data.len());
92 self.0.extend_from_slice(data);
93 }
94
95 #[inline]
97 pub fn clear(&mut self) {
98 self.0.zeroize();
99 self.0.truncate(0);
100 }
101
102 #[inline]
104 pub fn reserve(&mut self, extra: usize) {
105 self.ensure_capacity(self.len() + extra)
106 }
107
108 pub fn shrink_to_fit(&mut self) {
110 let len = self.0.len();
111 if self.0.capacity() > len {
112 let mut buf = Self::with_capacity(len);
115 buf.0.extend_from_slice(&self.0[..]);
116 mem::swap(&mut buf, self);
117 }
119 }
120
121 pub fn into_boxed_slice(mut self) -> Box<[u8]> {
123 self.shrink_to_fit();
124 self.into_vec().into_boxed_slice()
125 }
126
127 #[inline]
129 pub fn into_vec(mut self) -> Vec<u8> {
130 let mut v = Vec::new(); mem::swap(&mut v, &mut self.0);
133 v
134 }
135
136 #[cfg(feature = "crypto_box")]
137 pub(crate) fn as_vec_mut(&mut self) -> &mut Vec<u8> {
138 &mut self.0
139 }
140
141 pub(crate) fn splice(
142 &mut self,
143 range: Range<usize>,
144 iter: impl ExactSizeIterator<Item = u8>,
145 ) -> Result<(), Error> {
146 assert!(range.end >= range.start);
147 let rem_len = range.len();
148 let ins_len = iter.len();
149 if ins_len > rem_len {
150 self.reserve(ins_len - rem_len);
151 }
152 self.0.splice(range, iter);
153 Ok(())
154 }
155
156 pub fn as_hex(&self) -> HexRepr<&[u8]> {
158 HexRepr(self.0.as_ref())
159 }
160}
161
162impl Debug for SecretBytes {
163 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
164 if cfg!(test) {
165 f.debug_tuple("Secret")
166 .field(&MaybeStr(self.0.as_slice()))
167 .finish()
168 } else {
169 f.write_str("<secret>")
170 }
171 }
172}
173
174impl AsRef<[u8]> for SecretBytes {
175 fn as_ref(&self) -> &[u8] {
176 self.0.as_slice()
177 }
178}
179
180impl AsMut<[u8]> for SecretBytes {
181 fn as_mut(&mut self) -> &mut [u8] {
182 self.0.as_mut_slice()
183 }
184}
185
186impl Deref for SecretBytes {
187 type Target = [u8];
188
189 fn deref(&self) -> &Self::Target {
190 self.0.as_slice()
191 }
192}
193
194impl Drop for SecretBytes {
195 fn drop(&mut self) {
196 self.zeroize();
197 }
198}
199
200impl ConstantTimeEq for SecretBytes {
201 fn ct_eq(&self, other: &Self) -> Choice {
202 ConstantTimeEq::ct_eq(self.0.as_slice(), other.0.as_slice())
203 }
204}
205
206impl PartialEq for SecretBytes {
207 #[inline]
208 fn eq(&self, other: &Self) -> bool {
209 self.ct_eq(other).into()
210 }
211}
212impl Eq for SecretBytes {}
213
214impl hash::Hash for SecretBytes {
215 fn hash<H: hash::Hasher>(&self, state: &mut H) {
216 self.0.hash(state);
217 }
218}
219
220impl From<&[u8]> for SecretBytes {
221 fn from(inner: &[u8]) -> Self {
222 Self(inner.to_vec())
223 }
224}
225
226impl From<&str> for SecretBytes {
227 fn from(inner: &str) -> Self {
228 Self(inner.as_bytes().to_vec())
229 }
230}
231
232impl From<String> for SecretBytes {
233 fn from(inner: String) -> Self {
234 Self(inner.into_bytes())
235 }
236}
237
238impl From<Box<[u8]>> for SecretBytes {
239 fn from(inner: Box<[u8]>) -> Self {
240 Self(inner.into())
241 }
242}
243
244impl From<Vec<u8>> for SecretBytes {
245 fn from(inner: Vec<u8>) -> Self {
246 Self(inner)
247 }
248}
249
250impl PartialEq<&[u8]> for SecretBytes {
251 fn eq(&self, other: &&[u8]) -> bool {
252 self.0.eq(other)
253 }
254}
255
256impl PartialEq<Vec<u8>> for SecretBytes {
257 fn eq(&self, other: &Vec<u8>) -> bool {
258 self.0.eq(other)
259 }
260}
261
262impl WriteBuffer for SecretBytes {
263 fn buffer_write(&mut self, data: &[u8]) -> Result<(), Error> {
264 self.extend_from_slice(data);
265 Ok(())
266 }
267}
268
269impl ResizeBuffer for SecretBytes {
270 fn buffer_insert(&mut self, pos: usize, data: &[u8]) -> Result<(), Error> {
271 self.splice(pos..pos, data.iter().cloned())
272 }
273
274 fn buffer_remove(&mut self, range: Range<usize>) -> Result<(), Error> {
275 self.0.drain(range);
276 Ok(())
277 }
278
279 fn buffer_resize(&mut self, len: usize) -> Result<(), Error> {
280 self.ensure_capacity(len);
281 self.0.resize(len, 0u8);
282 Ok(())
283 }
284}
285
286impl Serialize for SecretBytes {
287 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288 where
289 S: Serializer,
290 {
291 serializer.serialize_bytes(self.as_ref())
292 }
293}
294
295impl<'de> Deserialize<'de> for SecretBytes {
296 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297 where
298 D: Deserializer<'de>,
299 {
300 deserializer.deserialize_bytes(SecVisitor)
301 }
302}
303
304struct SecVisitor;
305
306impl de::Visitor<'_> for SecVisitor {
307 type Value = SecretBytes;
308
309 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
310 formatter.write_str("bytes")
311 }
312
313 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
314 where
315 E: de::Error,
316 {
317 Ok(SecretBytes::from_slice(value))
318 }
319}
320
321#[cfg(test)]
322mod tests {
323 use super::super::tests::{test_resize_buffer, test_write_buffer};
324 use super::*;
325
326 #[test]
327 fn write_buffer_secret() {
328 test_write_buffer(SecretBytes::with_capacity(10));
329 }
330
331 #[test]
332 fn resize_buffer_secret() {
333 test_resize_buffer(SecretBytes::with_capacity(10));
334 }
335}