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(feature = "std")]
19use std::vec::Vec;
20#[cfg(all(not(feature = "std"), feature = "alloc"))]
21use alloc::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
110/// A variable-length vector of bytes that is securely zeroed when dropped
111#[derive(Clone, Zeroize, ZeroizeOnDrop)]
112pub struct SecretVec {
113    data: Vec<u8>,
114}
115
116impl SecretVec {
117    /// Create a new SecretVec.
118    ///
119    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
120    /// Moving a Vec<u8> is preferred for security as it ensures the original
121    /// memory allocation is controlled and zeroized by SecretVec.
122    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
123        Self { data: data.into() }
124    }
125
126    pub fn from_slice(slice: &[u8]) -> Self {
127        Self {
128            data: slice.to_vec(),
129        }
130    }
131    pub fn zeroed(len: usize) -> Self {
132        Self {
133            data: vec![0u8; len],
134        }
135    }
136    pub fn random<R: rand::RngCore + rand::CryptoRng>(rng: &mut R, len: usize) -> Self {
137        let mut data = vec![0u8; len];
138        rng.fill_bytes(&mut data);
139        Self { data }
140    }
141    pub fn len(&self) -> usize {
142        self.data.len()
143    }
144    pub fn is_empty(&self) -> bool {
145        self.data.is_empty()
146    }
147}
148
149impl From<Vec<u8>> for SecretVec {
150    fn from(data: Vec<u8>) -> Self {
151        Self::new(data)
152    }
153}
154
155impl AsRef<[u8]> for SecretVec {
156    fn as_ref(&self) -> &[u8] {
157        &self.data
158    }
159}
160
161impl AsMut<[u8]> for SecretVec {
162    fn as_mut(&mut self) -> &mut [u8] {
163        &mut self.data
164    }
165}
166
167impl Deref for SecretVec {
168    type Target = Vec<u8>;
169    fn deref(&self) -> &Self::Target {
170        &self.data
171    }
172}
173
174impl DerefMut for SecretVec {
175    fn deref_mut(&mut self) -> &mut Self::Target {
176        &mut self.data
177    }
178}
179
180impl PartialEq for SecretVec {
181    fn eq(&self, other: &Self) -> bool {
182        ct_eq(&self.data, &other.data)
183    }
184}
185
186impl Eq for SecretVec {}
187
188impl fmt::Debug for SecretVec {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190        write!(f, "SecretVec({})[REDACTED]", self.data.len())
191    }
192}
193
194impl SerializeSecret for SecretVec {
195    fn from_bytes(bytes: &[u8]) -> Result<Self> {
196        Ok(Self::from_slice(bytes))
197    }
198    fn to_bytes_zeroizing(&self) -> Zeroizing<Vec<u8>> {
199        Zeroizing::new(self.data.clone())
200    }
201}
202
203/// Base key type that provides secure memory handling
204#[derive(Clone, Zeroize, ZeroizeOnDrop)]
205pub struct Key {
206    data: Vec<u8>,
207}
208
209impl Key {
210    /// Create a new Key.
211    ///
212    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
213    /// Moving a Vec<u8> is preferred for security as it ensures the original
214    /// memory allocation is controlled and zeroized by Key.
215    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
216        Self {
217            data: data.into(),
218        }
219    }
220    pub fn new_zeros(len: usize) -> Self {
221        Self {
222            data: vec![0u8; len],
223        }
224    }
225    pub fn len(&self) -> usize {
226        self.data.len()
227    }
228    pub fn is_empty(&self) -> bool {
229        self.data.is_empty()
230    }
231}
232
233impl From<Vec<u8>> for Key {
234    fn from(data: Vec<u8>) -> Self {
235        Self::new(data)
236    }
237}
238
239impl AsRef<[u8]> for Key {
240    fn as_ref(&self) -> &[u8] {
241        &self.data
242    }
243}
244
245impl AsMut<[u8]> for Key {
246    fn as_mut(&mut self) -> &mut [u8] {
247        &mut self.data
248    }
249}
250
251impl SerializeSecret for Key {
252    fn from_bytes(bytes: &[u8]) -> Result<Self> {
253        Ok(Self::new(bytes))
254    }
255    fn to_bytes_zeroizing(&self) -> Zeroizing<Vec<u8>> {
256        Zeroizing::new(self.data.clone())
257    }
258}
259
260/// Wrapper for public key data
261#[derive(Clone, Zeroize)]
262pub struct PublicKey {
263    data: Vec<u8>,
264}
265
266impl PublicKey {
267    /// Create a new PublicKey.
268    ///
269    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
270    /// Moving a Vec<u8> avoids unnecessary allocation.
271    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
272        Self {
273            data: data.into(),
274        }
275    }
276    pub fn len(&self) -> usize {
277        self.data.len()
278    }
279    pub fn is_empty(&self) -> bool {
280        self.data.is_empty()
281    }
282}
283
284impl From<Vec<u8>> for PublicKey {
285    fn from(data: Vec<u8>) -> Self {
286        Self::new(data)
287    }
288}
289
290impl AsRef<[u8]> for PublicKey {
291    fn as_ref(&self) -> &[u8] {
292        &self.data
293    }
294}
295
296impl AsMut<[u8]> for PublicKey {
297    fn as_mut(&mut self) -> &mut [u8] {
298        &mut self.data
299    }
300}
301
302impl Serialize for PublicKey {
303    fn to_bytes(&self) -> Vec<u8> {
304        self.data.clone()
305    }
306    fn from_bytes(bytes: &[u8]) -> Result<Self> {
307        Ok(Self::new(bytes))
308    }
309}
310
311/// Wrapper for ciphertext data
312#[derive(Clone)]
313pub struct Ciphertext {
314    data: Vec<u8>,
315}
316
317impl Ciphertext {
318    /// Create a new Ciphertext.
319    ///
320    /// Accepts `Vec<u8>` (move) or `&[u8]` (copy).
321    /// Moving a Vec<u8> avoids unnecessary allocation, which is critical
322    /// for large ciphertexts.
323    pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
324        Self {
325            data: data.into(),
326        }
327    }
328    pub fn len(&self) -> usize {
329        self.data.len()
330    }
331    pub fn is_empty(&self) -> bool {
332        self.data.is_empty()
333    }
334}
335
336impl From<Vec<u8>> for Ciphertext {
337    fn from(data: Vec<u8>) -> Self {
338        Self::new(data)
339    }
340}
341
342impl AsRef<[u8]> for Ciphertext {
343    fn as_ref(&self) -> &[u8] {
344        &self.data
345    }
346}
347
348impl AsMut<[u8]> for Ciphertext {
349    fn as_mut(&mut self) -> &mut [u8] {
350        &mut self.data
351    }
352}
353
354impl Serialize for Ciphertext {
355    fn to_bytes(&self) -> Vec<u8> {
356        self.data.clone()
357    }
358    fn from_bytes(bytes: &[u8]) -> Result<Self> {
359        Ok(Self::new(bytes))
360    }
361}