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