askar_storage/protect/
pass_key.rs

1use zeroize::Zeroize;
2
3use std::{
4    borrow::Cow,
5    fmt::{self, Debug, Formatter},
6    mem::ManuallyDrop,
7    ops::Deref,
8};
9
10/// A possibly-empty password or key used to derive a store key
11#[derive(Clone, Default)]
12pub struct PassKey<'a>(Option<Cow<'a, str>>);
13
14impl PassKey<'_> {
15    /// Create a scoped reference to the passkey
16    pub fn as_ref(&self) -> PassKey<'_> {
17        PassKey(Some(Cow::Borrowed(&**self)))
18    }
19
20    /// Create an empty passkey
21    pub fn empty() -> PassKey<'static> {
22        PassKey(None)
23    }
24
25    pub(crate) fn is_none(&self) -> bool {
26        self.0.is_none()
27    }
28
29    /// Convert to an owned instance, allocating if necessary
30    pub fn into_owned(self) -> PassKey<'static> {
31        let mut slf = ManuallyDrop::new(self);
32        let val = slf.0.take();
33        PassKey(match val {
34            None => None,
35            Some(Cow::Borrowed(s)) => Some(Cow::Owned(s.to_string())),
36            Some(Cow::Owned(s)) => Some(Cow::Owned(s)),
37        })
38    }
39}
40
41impl Debug for PassKey<'_> {
42    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
43        if cfg!(test) {
44            f.debug_tuple("PassKey").field(&self.0).finish()
45        } else {
46            f.debug_tuple("PassKey").field(&"<secret>").finish()
47        }
48    }
49}
50
51impl Deref for PassKey<'_> {
52    type Target = str;
53
54    fn deref(&self) -> &str {
55        match self.0.as_ref() {
56            None => "",
57            Some(s) => s.as_ref(),
58        }
59    }
60}
61
62impl Drop for PassKey<'_> {
63    fn drop(&mut self) {
64        self.zeroize();
65    }
66}
67
68impl<'a> From<&'a str> for PassKey<'a> {
69    fn from(inner: &'a str) -> Self {
70        Self(Some(Cow::Borrowed(inner)))
71    }
72}
73
74impl From<String> for PassKey<'_> {
75    fn from(inner: String) -> Self {
76        Self(Some(Cow::Owned(inner)))
77    }
78}
79
80impl<'a> From<Option<&'a str>> for PassKey<'a> {
81    fn from(inner: Option<&'a str>) -> Self {
82        Self(inner.map(Cow::Borrowed))
83    }
84}
85
86impl<'a> PartialEq<PassKey<'a>> for PassKey<'_> {
87    fn eq(&self, other: &PassKey<'a>) -> bool {
88        **self == **other
89    }
90}
91impl Eq for PassKey<'_> {}
92
93impl Zeroize for PassKey<'_> {
94    fn zeroize(&mut self) {
95        if let Some(Cow::Owned(mut s)) = self.0.take() {
96            s.zeroize();
97        }
98    }
99}