secure_gate/cloneable/
array.rs

1use crate::Fixed;
2use zeroize::Zeroize;
3
4/// Inner wrapper for a fixed-size array of bytes that can be safely cloned as a secret.
5///
6/// This struct wraps a `[u8; N]` array and implements the necessary traits for secure
7/// secret handling: `Clone` for duplication and `Zeroize` for secure memory wiping.
8/// The `zeroize(drop)` attribute ensures the array is zeroized when this struct is dropped.
9#[derive(Clone, PartialEq, Zeroize)]
10#[zeroize(drop)]
11pub struct CloneableArrayInner<const N: usize>([u8; N]);
12
13impl<const N: usize> crate::CloneSafe for CloneableArrayInner<N> {}
14
15/// A fixed-size array of bytes wrapped as a cloneable secret.
16///
17/// This type provides a secure wrapper around a `[u8; N]` array that can be safely cloned
18/// while ensuring the underlying data is properly zeroized when no longer needed.
19/// Use this for cryptographic keys, nonces, or other fixed-size secret data.
20///
21/// # Examples
22///
23/// ```
24/// # #[cfg(feature = "zeroize")]
25/// # {
26/// use secure_gate::CloneableArray;
27///
28/// // Create from an array
29/// let key: CloneableArray<32> = [42u8; 32].into();
30///
31/// // Access the inner array
32/// let inner = key.expose_inner();
33/// assert_eq!(inner.len(), 32);
34/// # }
35/// ```
36pub type CloneableArray<const N: usize> = Fixed<CloneableArrayInner<N>>;
37
38impl<const N: usize> CloneableArray<N> {
39    /// Returns a reference to the inner array without cloning.
40    ///
41    /// This method provides direct access to the wrapped `[u8; N]` array.
42    /// The reference is valid for the lifetime of the `CloneableArray`.
43    #[inline(always)]
44    pub const fn expose_inner(&self) -> &[u8; N] {
45        &self.expose_secret().0
46    }
47
48    /// Returns a mutable reference to the inner array.
49    ///
50    /// This method provides direct mutable access to the wrapped `[u8; N]` array.
51    /// Use this when you need to modify the array contents in-place.
52    #[inline(always)]
53    pub fn expose_inner_mut(&mut self) -> &mut [u8; N] {
54        &mut self.expose_secret_mut().0
55    }
56
57    /// Construct a cloneable array secret by building it in a closure.
58    ///
59    /// Same stack-minimization benefits as `CloneableString::init_with`.
60    ///
61    /// # Example
62    ///
63    /// ```
64    /// # #[cfg(feature = "zeroize")]
65    /// # {
66    /// use secure_gate::CloneableArray;
67    ///
68    /// let key = CloneableArray::<32>::init_with(|| {
69    ///     let mut arr = [0u8; 32];
70    ///     // Fill from some source...
71    ///     arr
72    /// });
73    /// # }
74    /// ```
75    #[must_use]
76    pub fn init_with<F>(constructor: F) -> Self
77    where
78        F: FnOnce() -> [u8; N],
79    {
80        let mut tmp = constructor();
81        let secret = Self::from(tmp);
82        tmp.zeroize();
83        secret
84    }
85
86    /// Fallible version of `init_with`.
87    ///
88    /// Same stack-minimization benefits as `init_with`, but allows for construction
89    /// that may fail with an error. Useful when reading secrets from fallible sources
90    /// like files or network connections.
91    pub fn try_init_with<F, E>(constructor: F) -> Result<Self, E>
92    where
93        F: FnOnce() -> Result<[u8; N], E>,
94    {
95        let mut tmp = constructor()?;
96        let secret = Self::from(tmp);
97        tmp.zeroize();
98        Ok(secret)
99    }
100}
101
102impl<const N: usize> From<[u8; N]> for CloneableArray<N> {
103    /// Wrap a `[u8; N]` array in a `CloneableArray`.
104    fn from(arr: [u8; N]) -> Self {
105        Fixed::new(CloneableArrayInner(arr))
106    }
107}