secure_gate/cloneable/
vec.rs

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