Skip to main content

dcrypt_api/
types.rs

1// File: crates/api/src/types.rs
2
3//! Core types with security guarantees for the dcrypt library
4//!
5//! This module provides fundamental type definitions that enforce
6//! compile-time and runtime guarantees for cryptographic operations.
7
8use crate::{
9    error::Error,
10    traits::serialize::{Serialize, SerializeSecret},
11    Result,
12};
13use core::fmt;
14use core::ops::{Deref, DerefMut};
15use dcrypt_internal::constant_time::ct_eq;
16use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
17
18#[cfg(all(not(feature = "std"), feature = "alloc"))]
19use alloc::vec::Vec;
20#[cfg(feature = "std")]
21use std::vec::Vec;
22
23/// A fixed-size array of bytes that is securely zeroed when dropped
24#[derive(Clone, Zeroize, ZeroizeOnDrop)]
25pub struct SecretBytes<const N: usize> {
26    data: [u8; N],
27}
28
29impl<const N: usize> SecretBytes<N> {
30    pub fn new(data: [u8; N]) -> Self {
31        Self { data }
32    }
33    pub fn from_slice(slice: &[u8]) -> Result<Self> {
34        if slice.len() != N {
35            return Err(Error::InvalidLength {
36                context: "SecretBytes::from_slice",
37                expected: N,
38                actual: slice.len(),
39            });
40        }
41        let mut data = [0u8; N];
42        data.copy_from_slice(slice);
43        Ok(Self { data })
44    }
45    pub fn zeroed() -> Self {
46        Self { data: [0u8; N] }
47    }
48    pub fn random<R: rand::RngCore + rand::CryptoRng>(rng: &mut R) -> Self {
49        let mut data = [0u8; N];
50        rng.fill_bytes(&mut data);
51        Self { data }
52    }
53    pub fn len(&self) -> usize {
54        N
55    }
56    pub fn is_empty(&self) -> bool {
57        N == 0
58    }
59}
60
61impl<const N: usize> AsRef<[u8]> for SecretBytes<N> {
62    fn as_ref(&self) -> &[u8] {
63        &self.data
64    }
65}
66
67impl<const N: usize> AsMut<[u8]> for SecretBytes<N> {
68    fn as_mut(&mut self) -> &mut [u8] {
69        &mut self.data
70    }
71}
72
73impl<const N: usize> Deref for SecretBytes<N> {
74    type Target = [u8; N];
75    fn deref(&self) -> &Self::Target {
76        &self.data
77    }
78}
79
80impl<const N: usize> DerefMut for SecretBytes<N> {
81    fn deref_mut(&mut self) -> &mut Self::Target {
82        &mut self.data
83    }
84}
85
86impl<const N: usize> PartialEq for SecretBytes<N> {
87    fn eq(&self, other: &Self) -> bool {
88        ct_eq(self.data, other.data)
89    }
90}
91
92impl<const N: usize> Eq for SecretBytes<N> {}
93
94impl<const N: usize> fmt::Debug for SecretBytes<N> {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        write!(f, "SecretBytes<{}>[REDACTED]", N)
97    }
98}
99
100impl<const N: usize> SerializeSecret for SecretBytes<N> {
101    fn from_bytes(bytes: &[u8]) -> Result<Self> {
102        Self::from_slice(bytes)
103    }
104    fn to_bytes_zeroizing(&self) -> Zeroizing<Vec<u8>> {
105        Zeroizing::new(self.data.to_vec())
106    }
107}
108
109/// A variable-length vector of bytes that is securely zeroed when dropped
110#[derive(Clone, Zeroize, ZeroizeOnDrop)]
111pub struct SecretVec {
112    data: Vec<u8>,
113}
114
115impl SecretVec {
116    /// Create a new SecretVec.
117    ///
118    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
119    /// Moving a Vec<u8> is preferred for security as it ensures the original
120    /// memory allocation is controlled and zeroized by SecretVec.
121    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
122        Self { data: data.into() }
123    }
124
125    pub fn from_slice(slice: &[u8]) -> Self {
126        Self {
127            data: slice.to_vec(),
128        }
129    }
130    pub fn zeroed(len: usize) -> Self {
131        Self {
132            data: vec![0u8; len],
133        }
134    }
135    pub fn random<R: rand::RngCore + rand::CryptoRng>(rng: &mut R, len: usize) -> Self {
136        let mut data = vec![0u8; len];
137        rng.fill_bytes(&mut data);
138        Self { data }
139    }
140    pub fn len(&self) -> usize {
141        self.data.len()
142    }
143    pub fn is_empty(&self) -> bool {
144        self.data.is_empty()
145    }
146}
147
148impl From<Vec<u8>> for SecretVec {
149    fn from(data: Vec<u8>) -> Self {
150        Self::new(data)
151    }
152}
153
154impl AsRef<[u8]> for SecretVec {
155    fn as_ref(&self) -> &[u8] {
156        &self.data
157    }
158}
159
160impl AsMut<[u8]> for SecretVec {
161    fn as_mut(&mut self) -> &mut [u8] {
162        &mut self.data
163    }
164}
165
166impl Deref for SecretVec {
167    type Target = Vec<u8>;
168    fn deref(&self) -> &Self::Target {
169        &self.data
170    }
171}
172
173impl DerefMut for SecretVec {
174    fn deref_mut(&mut self) -> &mut Self::Target {
175        &mut self.data
176    }
177}
178
179impl PartialEq for SecretVec {
180    fn eq(&self, other: &Self) -> bool {
181        ct_eq(&self.data, &other.data)
182    }
183}
184
185impl Eq for SecretVec {}
186
187impl fmt::Debug for SecretVec {
188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189        write!(f, "SecretVec({})[REDACTED]", self.data.len())
190    }
191}
192
193impl SerializeSecret for SecretVec {
194    fn from_bytes(bytes: &[u8]) -> Result<Self> {
195        Ok(Self::from_slice(bytes))
196    }
197    fn to_bytes_zeroizing(&self) -> Zeroizing<Vec<u8>> {
198        Zeroizing::new(self.data.clone())
199    }
200}
201
202/// Base key type that provides secure memory handling
203#[derive(Clone, Zeroize, ZeroizeOnDrop)]
204pub struct Key {
205    data: Vec<u8>,
206}
207
208impl Key {
209    /// Create a new Key.
210    ///
211    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
212    /// Moving a Vec<u8> is preferred for security as it ensures the original
213    /// memory allocation is controlled and zeroized by Key.
214    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
215        Self { data: data.into() }
216    }
217    pub fn new_zeros(len: usize) -> Self {
218        Self {
219            data: vec![0u8; len],
220        }
221    }
222    pub fn len(&self) -> usize {
223        self.data.len()
224    }
225    pub fn is_empty(&self) -> bool {
226        self.data.is_empty()
227    }
228}
229
230impl From<Vec<u8>> for Key {
231    fn from(data: Vec<u8>) -> Self {
232        Self::new(data)
233    }
234}
235
236impl AsRef<[u8]> for Key {
237    fn as_ref(&self) -> &[u8] {
238        &self.data
239    }
240}
241
242impl AsMut<[u8]> for Key {
243    fn as_mut(&mut self) -> &mut [u8] {
244        &mut self.data
245    }
246}
247
248impl SerializeSecret for Key {
249    fn from_bytes(bytes: &[u8]) -> Result<Self> {
250        Ok(Self::new(bytes))
251    }
252    fn to_bytes_zeroizing(&self) -> Zeroizing<Vec<u8>> {
253        Zeroizing::new(self.data.clone())
254    }
255}
256
257/// Wrapper for public key data
258#[derive(Clone, Zeroize)]
259pub struct PublicKey {
260    data: Vec<u8>,
261}
262
263impl PublicKey {
264    /// Create a new PublicKey.
265    ///
266    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
267    /// Moving a Vec<u8> avoids unnecessary allocation.
268    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
269        Self { data: data.into() }
270    }
271    pub fn len(&self) -> usize {
272        self.data.len()
273    }
274    pub fn is_empty(&self) -> bool {
275        self.data.is_empty()
276    }
277}
278
279impl From<Vec<u8>> for PublicKey {
280    fn from(data: Vec<u8>) -> Self {
281        Self::new(data)
282    }
283}
284
285impl AsRef<[u8]> for PublicKey {
286    fn as_ref(&self) -> &[u8] {
287        &self.data
288    }
289}
290
291impl AsMut<[u8]> for PublicKey {
292    fn as_mut(&mut self) -> &mut [u8] {
293        &mut self.data
294    }
295}
296
297impl Serialize for PublicKey {
298    fn to_bytes(&self) -> Vec<u8> {
299        self.data.clone()
300    }
301    fn from_bytes(bytes: &[u8]) -> Result<Self> {
302        Ok(Self::new(bytes))
303    }
304}
305
306/// Wrapper for ciphertext data
307#[derive(Clone)]
308pub struct Ciphertext {
309    data: Vec<u8>,
310}
311
312impl Ciphertext {
313    /// Create a new Ciphertext.
314    ///
315    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
316    /// Moving a Vec<u8> avoids unnecessary allocation, which is critical
317    /// for large ciphertexts.
318    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
319        Self { data: data.into() }
320    }
321    pub fn len(&self) -> usize {
322        self.data.len()
323    }
324    pub fn is_empty(&self) -> bool {
325        self.data.is_empty()
326    }
327}
328
329impl From<Vec<u8>> for Ciphertext {
330    fn from(data: Vec<u8>) -> Self {
331        Self::new(data)
332    }
333}
334
335impl AsRef<[u8]> for Ciphertext {
336    fn as_ref(&self) -> &[u8] {
337        &self.data
338    }
339}
340
341impl AsMut<[u8]> for Ciphertext {
342    fn as_mut(&mut self) -> &mut [u8] {
343        &mut self.data
344    }
345}
346
347impl Serialize for Ciphertext {
348    fn to_bytes(&self) -> Vec<u8> {
349        self.data.clone()
350    }
351    fn from_bytes(bytes: &[u8]) -> Result<Self> {
352        Ok(Self::new(bytes))
353    }
354}