Skip to main content

asjeeves_encryption/
sensitive.rs

1use std::fmt;
2use std::ops::Deref;
3use std::pin::Pin;
4
5use zeroize::{Zeroize, Zeroizing};
6
7/// NewType wrapper for sensitive values
8/// - Uses `Zeroizing` to ensure the value is zero'ed out when
9///   it leaves scope.
10/// - Uses `Debug` to ensure its not leaked through logs and tracing.
11/// - Uses `Pin` to ensure it cannot move (which can cause leakes)
12pub struct Sensitive<T: Zeroize>(Pin<Box<Zeroizing<T>>>);
13
14impl<T> Sensitive<T>
15where
16    T: Zeroize,
17{
18    pub fn new(inner: T) -> Self {
19        let inner = Zeroizing::new(inner);
20        let inner = Box::pin(inner);
21
22        Self(inner)
23    }
24}
25impl<T> fmt::Debug for Sensitive<T>
26where
27    T: Zeroize,
28{
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.debug_struct("Sensitive").finish_non_exhaustive()
31    }
32}
33
34impl<T> Deref for Sensitive<T>
35where
36    T: Deref + Zeroize,
37{
38    type Target = T;
39
40    fn deref(&self) -> &Self::Target {
41        self.0.deref()
42    }
43}
44
45#[cfg(test)]
46mod test {
47    use super::*;
48    use std::ops::Deref;
49
50    #[test]
51    fn it_hides_sensitive_info() {
52        let data = vec![1u8, 2u8];
53        let s: Sensitive<Vec<u8>> = Sensitive::new(data);
54
55        let dbg = format!("{:?}", s);
56
57        assert_eq!("Sensitive { .. }", dbg);
58        assert_eq!(&vec![1u8, 2u8], s.deref());
59    }
60}