Skip to main content

nexus_sdk/types/
secret.rs

1use zeroize::Zeroize;
2
3/// A redacted, zeroized wrapper for secret values.
4///
5/// This intentionally does not implement `Deref` to reduce accidental leakage
6/// via APIs that might log or format values.
7pub struct Secret<T: Zeroize>(zeroize::Zeroizing<T>);
8
9impl<T: Zeroize> Secret<T> {
10    pub fn new(value: T) -> Self {
11        Self(zeroize::Zeroizing::new(value))
12    }
13
14    pub fn expose(&self) -> &T {
15        &self.0
16    }
17
18    pub fn expose_mut(&mut self) -> &mut T {
19        &mut self.0
20    }
21
22    /// Move out the wrapped value while preserving zeroization-on-drop.
23    pub fn into_zeroizing(self) -> zeroize::Zeroizing<T> {
24        self.0
25    }
26}
27
28impl<T: Zeroize> From<T> for Secret<T> {
29    fn from(value: T) -> Self {
30        Self::new(value)
31    }
32}
33
34impl<T: Zeroize + Clone> Clone for Secret<T> {
35    fn clone(&self) -> Self {
36        Self::new(self.expose().clone())
37    }
38}
39
40impl<T: Zeroize + PartialEq> PartialEq for Secret<T> {
41    fn eq(&self, other: &Self) -> bool {
42        self.expose() == other.expose()
43    }
44}
45
46impl<T: Zeroize + Eq> Eq for Secret<T> {}
47
48impl<T: Zeroize> std::fmt::Debug for Secret<T> {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "Secret([Redacted: *****])")
51    }
52}
53
54impl<T: Zeroize> std::fmt::Display for Secret<T> {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        write!(f, "[Redacted: *****]")
57    }
58}