1use crate::{
10 error::Error,
11 traits::serialize::{Serialize, SerializeSecret},
12 Result,
13};
14use core::fmt;
15use core::ops::{Deref, DerefMut};
16use dcrypt_internal::constant_time::ct_eq;
17pub use dcrypt_internal::zeroing::ZeroizingBytes;
18use dcrypt_internal::{
19 random::try_fill_bytes_zeroing_on_error,
20 zeroing::{
21 boxed_bytes_from_slice, boxed_bytes_zeroed, zeroizing_bytes_from_slice, Zeroize,
22 ZeroizeOnDrop, Zeroizing,
23 },
24};
25
26#[cfg(not(feature = "std"))]
27use alloc::{boxed::Box, vec::Vec};
28#[cfg(feature = "std")]
29use std::{boxed::Box, vec::Vec};
30
31#[derive(Clone)]
33pub struct SecretBytes<const N: usize> {
34 data: [u8; N],
35}
36
37impl<const N: usize> Zeroize for SecretBytes<N> {
38 fn zeroize(&mut self) {
39 self.data.zeroize();
40 }
41}
42
43impl<const N: usize> ZeroizeOnDrop for SecretBytes<N> {}
44
45impl<const N: usize> Drop for SecretBytes<N> {
46 fn drop(&mut self) {
47 self.zeroize();
48 }
49}
50
51impl<const N: usize> SecretBytes<N> {
52 pub fn new(data: [u8; N]) -> Self {
53 Self { data }
54 }
55 pub fn from_slice(slice: &[u8]) -> Result<Self> {
56 if slice.len() != N {
57 return Err(Error::InvalidLength {
58 context: "SecretBytes::from_slice",
59 expected: N,
60 actual: slice.len(),
61 });
62 }
63 let mut data = [0u8; N];
64 data.copy_from_slice(slice);
65 Ok(Self { data })
66 }
67 pub fn zeroed() -> Self {
68 Self { data: [0u8; N] }
69 }
70 pub fn random<R: dcrypt_internal::random::CryptoRng + ?Sized>(rng: &mut R) -> Result<Self> {
71 let mut data = [0u8; N];
72 try_fill_bytes_zeroing_on_error(rng, &mut data).map_err(|_| {
73 Error::RandomGenerationError {
74 context: "SecretBytes::random",
75 #[cfg(feature = "std")]
76 message: "caller-provided randomness source failed".into(),
77 }
78 })?;
79 Ok(Self { data })
80 }
81 pub fn len(&self) -> usize {
82 N
83 }
84 pub fn is_empty(&self) -> bool {
85 N == 0
86 }
87
88 pub fn to_bytes_zeroizing_boxed(&self) -> ZeroizingBytes {
90 zeroizing_bytes_from_slice(&self.data)
91 }
92}
93
94impl<const N: usize> AsRef<[u8]> for SecretBytes<N> {
95 fn as_ref(&self) -> &[u8] {
96 &self.data
97 }
98}
99
100impl<const N: usize> AsMut<[u8]> for SecretBytes<N> {
101 fn as_mut(&mut self) -> &mut [u8] {
102 &mut self.data
103 }
104}
105
106impl<const N: usize> Deref for SecretBytes<N> {
107 type Target = [u8; N];
108 fn deref(&self) -> &Self::Target {
109 &self.data
110 }
111}
112
113impl<const N: usize> DerefMut for SecretBytes<N> {
114 fn deref_mut(&mut self) -> &mut Self::Target {
115 &mut self.data
116 }
117}
118
119impl<const N: usize> PartialEq for SecretBytes<N> {
120 fn eq(&self, other: &Self) -> bool {
121 ct_eq(self.data.as_slice(), other.data.as_slice())
122 }
123}
124
125impl<const N: usize> Eq for SecretBytes<N> {}
126
127impl<const N: usize> fmt::Debug for SecretBytes<N> {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 write!(f, "SecretBytes<{}>[REDACTED]", N)
130 }
131}
132
133impl<const N: usize> SerializeSecret for SecretBytes<N> {
134 fn from_bytes(bytes: &[u8]) -> Result<Self> {
135 Self::from_slice(bytes)
136 }
137 fn to_bytes_zeroizing(&self) -> ZeroizingBytes {
138 self.to_bytes_zeroizing_boxed()
139 }
140}
141
142pub struct SecretVec {
147 data: Box<[u8]>,
148}
149
150impl Zeroize for SecretVec {
151 fn zeroize(&mut self) {
152 self.data.zeroize();
153 }
154}
155
156impl ZeroizeOnDrop for SecretVec {}
157
158impl Drop for SecretVec {
159 fn drop(&mut self) {
160 self.zeroize();
161 }
162}
163
164impl SecretVec {
165 pub fn new(data: Box<[u8]>) -> Self {
171 Self { data }
172 }
173
174 pub fn from_slice(slice: &[u8]) -> Self {
176 Self::new(boxed_bytes_from_slice(slice))
177 }
178
179 pub fn empty() -> Self {
181 Self::new(boxed_bytes_zeroed(0))
182 }
183
184 pub fn zeroed(len: usize) -> Self {
186 Self::new(boxed_bytes_zeroed(len))
187 }
188
189 pub fn random<R: dcrypt_internal::random::CryptoRng + ?Sized>(
192 rng: &mut R,
193 len: usize,
194 ) -> Result<Self> {
195 let mut data = boxed_bytes_zeroed(len);
196 try_fill_bytes_zeroing_on_error(rng, &mut data).map_err(|_| {
197 Error::RandomGenerationError {
198 context: "SecretVec::random",
199 #[cfg(feature = "std")]
200 message: "caller-provided randomness source failed".into(),
201 }
202 })?;
203 Ok(Self::new(data))
204 }
205 pub fn len(&self) -> usize {
206 self.data.len()
207 }
208 pub fn is_empty(&self) -> bool {
209 self.data.is_empty()
210 }
211
212 pub fn as_slice(&self) -> &[u8] {
214 &self.data
215 }
216
217 pub fn as_mut_slice(&mut self) -> &mut [u8] {
222 &mut self.data
223 }
224
225 pub fn to_bytes_zeroizing_boxed(&self) -> ZeroizingBytes {
227 zeroizing_bytes_from_slice(&self.data)
228 }
229
230 pub fn into_bytes_zeroizing_boxed(mut self) -> ZeroizingBytes {
233 let data = core::mem::replace(&mut self.data, boxed_bytes_zeroed(0));
234 Zeroizing::new(data)
235 }
236
237 pub fn capacity(&self) -> usize {
239 self.data.len()
240 }
241
242 pub fn extend_from_slice(&mut self, slice: &[u8]) {
245 let new_len = self
246 .data
247 .len()
248 .checked_add(slice.len())
249 .expect("SecretVec length overflow");
250 let mut replacement = boxed_bytes_zeroed(new_len);
251 replacement[..self.data.len()].copy_from_slice(&self.data);
252 replacement[self.data.len()..].copy_from_slice(slice);
253 self.replace_and_zeroize(replacement);
254 }
255
256 pub fn resize(&mut self, new_len: usize, value: u8) {
258 if new_len <= self.data.len() {
259 self.truncate(new_len);
260 return;
261 }
262
263 let mut replacement = boxed_bytes_zeroed(new_len);
264 replacement[..self.data.len()].copy_from_slice(&self.data);
265 replacement[self.data.len()..].fill(value);
266 self.replace_and_zeroize(replacement);
267 }
268
269 pub fn truncate(&mut self, len: usize) {
271 if len >= self.data.len() {
272 return;
273 }
274
275 let replacement = boxed_bytes_from_slice(&self.data[..len]);
276 self.replace_and_zeroize(replacement);
277 }
278
279 pub fn clear(&mut self) {
281 self.replace_and_zeroize(boxed_bytes_zeroed(0));
282 }
283
284 pub fn push(&mut self, value: u8) {
286 self.extend_from_slice(&[value]);
287 }
288
289 pub fn pop(&mut self) -> Option<u8> {
291 let value = self.data.last().copied()?;
292 self.truncate(self.data.len() - 1);
293 Some(value)
294 }
295
296 fn replace_and_zeroize(&mut self, replacement: Box<[u8]>) {
297 self.data.zeroize();
298 self.data = replacement;
299 }
300}
301
302impl Clone for SecretVec {
303 fn clone(&self) -> Self {
304 Self::from_slice(&self.data)
305 }
306}
307
308impl From<Box<[u8]>> for SecretVec {
309 fn from(data: Box<[u8]>) -> Self {
310 Self::new(data)
311 }
312}
313
314impl AsRef<[u8]> for SecretVec {
315 fn as_ref(&self) -> &[u8] {
316 self.data.as_ref()
317 }
318}
319
320impl AsMut<[u8]> for SecretVec {
321 fn as_mut(&mut self) -> &mut [u8] {
322 self.data.as_mut()
323 }
324}
325
326impl Deref for SecretVec {
327 type Target = [u8];
328 fn deref(&self) -> &Self::Target {
329 self.data.as_ref()
330 }
331}
332
333impl DerefMut for SecretVec {
334 fn deref_mut(&mut self) -> &mut Self::Target {
335 self.data.as_mut()
336 }
337}
338
339impl PartialEq for SecretVec {
340 fn eq(&self, other: &Self) -> bool {
341 ct_eq(self.data.as_ref(), other.data.as_ref())
342 }
343}
344
345impl Eq for SecretVec {}
346
347impl fmt::Debug for SecretVec {
348 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349 write!(f, "SecretVec({})[REDACTED]", self.data.len())
350 }
351}
352
353impl SerializeSecret for SecretVec {
354 fn from_bytes(bytes: &[u8]) -> Result<Self> {
355 Ok(Self::from_slice(bytes))
356 }
357 fn to_bytes_zeroizing(&self) -> ZeroizingBytes {
358 self.to_bytes_zeroizing_boxed()
359 }
360}
361
362#[cfg(test)]
363mod secret_vec_tests {
364 use super::{Key, SecretBytes, SecretVec};
365 use crate::traits::SerializeSecret;
366 use dcrypt_internal::random::{CryptoRng, Error as RandomError, RngCore};
367
368 #[test]
369 fn constructor_uses_exact_size_storage() {
370 let secret = SecretVec::new([0xA5; 4].into());
371
372 assert_eq!(secret.as_slice(), &[0xA5; 4]);
373 assert_eq!(secret.capacity(), secret.len());
374 }
375
376 #[test]
377 fn shrinking_operations_wipe_removed_slots() {
378 let mut secret = SecretVec::from_slice(&[1, 2, 3, 4, 5, 6]);
379
380 secret.truncate(4);
381 assert_eq!(secret.as_slice(), &[1, 2, 3, 4]);
382 assert_eq!(secret.capacity(), secret.len());
383
384 secret.resize(2, 0xFF);
385 assert_eq!(secret.as_slice(), &[1, 2]);
386 assert_eq!(secret.capacity(), secret.len());
387
388 assert_eq!(secret.pop(), Some(2));
389 assert_eq!(secret.as_slice(), &[1]);
390 assert_eq!(secret.capacity(), secret.len());
391
392 secret.clear();
393 assert!(secret.is_empty());
394 assert_eq!(secret.capacity(), secret.len());
395 }
396
397 #[test]
398 fn growth_and_shrink_replace_allocations_securely() {
399 let mut secret = SecretVec::from_slice(&[0x11; 4]);
400 secret.extend_from_slice(&[0x22, 0x33]);
401 assert_eq!(secret.capacity(), 6);
402 assert_eq!(secret.as_slice(), &[0x11, 0x11, 0x11, 0x11, 0x22, 0x33]);
403 }
404
405 #[test]
406 fn exact_size_serialization_supports_copy_and_ownership_transfer() {
407 let fixed = SecretBytes::<4>::new([1, 2, 3, 4]);
408 let fixed_bytes = fixed.to_bytes_zeroizing_boxed();
409 assert_eq!(&**fixed_bytes, &[1, 2, 3, 4]);
410 let trait_fixed_bytes = fixed.to_bytes_zeroizing();
411 assert_eq!(&**trait_fixed_bytes, &[1, 2, 3, 4]);
412
413 let secret = SecretVec::from_slice(&[5, 6, 7]);
414 let copied = secret.to_bytes_zeroizing_boxed();
415 assert_eq!(&**copied, &[5, 6, 7]);
416 let trait_copied = secret.to_bytes_zeroizing();
417 assert_eq!(&**trait_copied, &[5, 6, 7]);
418
419 let transferred = secret.into_bytes_zeroizing_boxed();
420 assert_eq!(&**transferred, &[5, 6, 7]);
421
422 let key = Key::from_slice(&[8, 9]);
423 let key_bytes = key.to_bytes_zeroizing_boxed();
424 assert_eq!(&**key_bytes, &[8, 9]);
425 let trait_key_bytes = key.to_bytes_zeroizing();
426 assert_eq!(&**trait_key_bytes, &[8, 9]);
427 }
428
429 struct PartiallyFailingRng;
430
431 impl RngCore for PartiallyFailingRng {
432 fn try_fill_bytes(&mut self, destination: &mut [u8]) -> Result<(), RandomError> {
433 let written = core::cmp::min(destination.len(), 5);
434 destination[..written].fill(0xA5);
435 Err(RandomError)
436 }
437 }
438
439 impl CryptoRng for PartiallyFailingRng {}
440
441 #[test]
442 fn random_secret_constructors_propagate_caller_rng_failure() {
443 let mut rng = PartiallyFailingRng;
444 assert!(SecretBytes::<32>::random(&mut rng).is_err());
445 assert!(SecretVec::random(&mut rng, 32).is_err());
446 }
447}
448
449#[derive(Clone)]
451pub struct Key {
452 data: Box<[u8]>,
453}
454
455impl Zeroize for Key {
456 fn zeroize(&mut self) {
457 self.data.zeroize();
458 }
459}
460
461impl ZeroizeOnDrop for Key {}
462
463impl Drop for Key {
464 fn drop(&mut self) {
465 self.zeroize();
466 }
467}
468
469impl Key {
470 pub fn new(data: &[u8]) -> Self {
476 Self::from_boxed_slice(boxed_bytes_from_slice(data))
477 }
478
479 pub fn from_boxed_slice(data: Box<[u8]>) -> Self {
481 Self { data }
482 }
483
484 pub fn from_slice(data: &[u8]) -> Self {
486 Self::new(data)
487 }
488
489 pub fn new_zeros(len: usize) -> Self {
490 Self::from_boxed_slice(boxed_bytes_zeroed(len))
491 }
492 pub fn len(&self) -> usize {
493 self.data.len()
494 }
495 pub fn is_empty(&self) -> bool {
496 self.data.is_empty()
497 }
498
499 pub fn to_bytes_zeroizing_boxed(&self) -> ZeroizingBytes {
501 zeroizing_bytes_from_slice(&self.data)
502 }
503}
504
505impl From<Box<[u8]>> for Key {
506 fn from(data: Box<[u8]>) -> Self {
507 Self::from_boxed_slice(data)
508 }
509}
510
511impl AsRef<[u8]> for Key {
512 fn as_ref(&self) -> &[u8] {
513 self.data.as_ref()
514 }
515}
516
517impl AsMut<[u8]> for Key {
518 fn as_mut(&mut self) -> &mut [u8] {
519 self.data.as_mut()
520 }
521}
522
523impl SerializeSecret for Key {
524 fn from_bytes(bytes: &[u8]) -> Result<Self> {
525 Ok(Self::from_slice(bytes))
526 }
527 fn to_bytes_zeroizing(&self) -> ZeroizingBytes {
528 self.to_bytes_zeroizing_boxed()
529 }
530}
531
532#[derive(Clone)]
534pub struct PublicKey {
535 data: Vec<u8>,
536}
537
538impl PublicKey {
539 pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
544 Self { data: data.into() }
545 }
546 pub fn len(&self) -> usize {
547 self.data.len()
548 }
549 pub fn is_empty(&self) -> bool {
550 self.data.is_empty()
551 }
552}
553
554impl From<Vec<u8>> for PublicKey {
555 fn from(data: Vec<u8>) -> Self {
556 Self::new(data)
557 }
558}
559
560impl AsRef<[u8]> for PublicKey {
561 fn as_ref(&self) -> &[u8] {
562 &self.data
563 }
564}
565
566impl AsMut<[u8]> for PublicKey {
567 fn as_mut(&mut self) -> &mut [u8] {
568 &mut self.data
569 }
570}
571
572impl Serialize for PublicKey {
573 fn to_bytes(&self) -> Vec<u8> {
574 self.data.clone()
575 }
576 fn from_bytes(bytes: &[u8]) -> Result<Self> {
577 Ok(Self::new(bytes))
578 }
579}
580
581#[derive(Clone)]
583pub struct Ciphertext {
584 data: Vec<u8>,
585}
586
587impl Ciphertext {
588 pub fn new<T: Into<Vec<u8>>>(data: T) -> Self {
594 Self { data: data.into() }
595 }
596 pub fn len(&self) -> usize {
597 self.data.len()
598 }
599 pub fn is_empty(&self) -> bool {
600 self.data.is_empty()
601 }
602}
603
604impl From<Vec<u8>> for Ciphertext {
605 fn from(data: Vec<u8>) -> Self {
606 Self::new(data)
607 }
608}
609
610impl AsRef<[u8]> for Ciphertext {
611 fn as_ref(&self) -> &[u8] {
612 &self.data
613 }
614}
615
616impl AsMut<[u8]> for Ciphertext {
617 fn as_mut(&mut self) -> &mut [u8] {
618 &mut self.data
619 }
620}
621
622impl Serialize for Ciphertext {
623 fn to_bytes(&self) -> Vec<u8> {
624 self.data.clone()
625 }
626 fn from_bytes(bytes: &[u8]) -> Result<Self> {
627 Ok(Self::new(bytes))
628 }
629}