seed_keeper_core/
seed.rs

1//! Utilities for using secure Seeds
2use rand::prelude::*;
3use std::ops::Deref;
4use std::ops::DerefMut;
5use zeroize::Zeroize;
6use zeroize::{ZeroizeOnDrop, Zeroizing};
7
8/// Generates and returns a random [Seed], with memory [Zeroize]d.
9///
10/// Uses [rand::thread_rng] to generate a random [Seed]
11///
12/// # Example
13///
14/// ```rust
15/// use seed_keeper_core::seed::{rand_seed, Seed};
16///
17/// let seed = rand_seed();
18/// assert_eq!(seed.len(), 32);
19/// ````
20pub fn rand_seed() -> Zeroizing<[u8; 32]> {
21    let mut rng = rand::thread_rng();
22    let mut output_key_material = Zeroizing::new([0u8; 32]); // default size is 32 bytes
23
24    rng.fill_bytes(&mut *output_key_material);
25
26    Zeroizing::new(*output_key_material)
27}
28
29/// Seed is a wrapper around [u8; 32] to ensure it is always 32 bytes
30///
31/// To ensure users don't expose bytes to vulnerable memory,
32/// we insist they wrap their bytes in [Zeroizing] when they pass
33/// the bytes to [Seed].
34#[derive(Clone, Debug, PartialEq)]
35pub struct Seed(Zeroizing<[u8; 32]>);
36
37impl Seed {
38    /// Creates a new [Seed] from a [u8; 32]
39    pub fn new(seed: Zeroizing<[u8; 32]>) -> Self {
40        Self(seed)
41    }
42}
43
44impl Default for Seed {
45    fn default() -> Self {
46        Self::new(Zeroizing::new([0u8; 32]))
47    }
48}
49
50impl Zeroize for Seed {
51    fn zeroize(&mut self) {
52        self.0.zeroize();
53    }
54}
55
56impl From<Vec<u8>> for Seed {
57    fn from(seed: Vec<u8>) -> Self {
58        let mut bytes = [0u8; 32];
59        bytes.copy_from_slice(&seed[..32]);
60
61        Self::new(Zeroizing::new(bytes))
62    }
63}
64
65/// Zeroizes on drop
66impl ZeroizeOnDrop for Seed {}
67
68impl Deref for Seed {
69    type Target = [u8];
70
71    fn deref(&self) -> &Self::Target {
72        &*self.0
73    }
74}
75
76impl DerefMut for Seed {
77    fn deref_mut(&mut self) -> &mut Self::Target {
78        &mut *self.0
79    }
80}
81
82impl AsRef<[u8]> for Seed {
83    fn as_ref(&self) -> &[u8] {
84        &*self.0
85    }
86}
87
88impl AsRef<[u8; 32]> for Seed {
89    fn as_ref(&self) -> &[u8; 32] {
90        &self.0
91    }
92}
93
94impl PartialEq<Seed> for [u8] {
95    fn eq(&self, other: &Seed) -> bool {
96        self[..] == other[..]
97    }
98}
99
100impl PartialEq<Seed> for [u8; 32] {
101    fn eq(&self, other: &Seed) -> bool {
102        self[..] == other[..]
103    }
104}
105
106#[cfg(test)]
107mod seed_tests {
108    use super::*;
109
110    // using rand_seed works too
111    #[test]
112    fn rand_seed_works() {
113        let seed = rand_seed();
114
115        assert_eq!(seed.len(), 32);
116    }
117}