torrust_tracker/shared/crypto/
keys.rs

1//! This module contains logic related to cryptographic keys.
2pub mod seeds {
3    //! This module contains logic related to cryptographic seeds.
4    //!
5    //! Specifically, it contains the logic for storing the seed and providing
6    //! it to other modules.
7    //!
8    //! A **seed** is a pseudo-random number that is used as a secret key for
9    //! cryptographic operations.
10    use self::detail::CURRENT_SEED;
11    use crate::shared::crypto::ephemeral_instance_keys::{Seed, RANDOM_SEED};
12
13    /// This trait is for structures that can keep and provide a seed.
14    pub trait Keeper {
15        type Seed: Sized + Default + AsMut<[u8]>;
16
17        /// It returns a reference to the seed that is keeping.
18        fn get_seed() -> &'static Self::Seed;
19    }
20
21    /// The seed keeper for the instance. When the application is running
22    /// in production, this will be the seed keeper that is used.
23    pub struct Instance;
24
25    /// The seed keeper for the current execution. It's a facade at compilation
26    /// time that will either be the instance seed keeper (with a randomly
27    /// generated key for production) or the zeroed seed keeper.
28    pub struct Current;
29
30    impl Keeper for Instance {
31        type Seed = Seed;
32
33        fn get_seed() -> &'static Self::Seed {
34            &RANDOM_SEED
35        }
36    }
37
38    impl Keeper for Current {
39        type Seed = Seed;
40
41        #[allow(clippy::needless_borrow)]
42        fn get_seed() -> &'static Self::Seed {
43            &CURRENT_SEED
44        }
45    }
46
47    #[cfg(test)]
48    mod tests {
49        use super::detail::ZEROED_TEST_SEED;
50        use super::{Current, Instance, Keeper};
51        use crate::shared::crypto::ephemeral_instance_keys::Seed;
52
53        pub struct ZeroedTestSeed;
54
55        impl Keeper for ZeroedTestSeed {
56            type Seed = Seed;
57
58            #[allow(clippy::needless_borrow)]
59            fn get_seed() -> &'static Self::Seed {
60                &ZEROED_TEST_SEED
61            }
62        }
63
64        #[test]
65        fn the_default_seed_and_the_zeroed_seed_should_be_the_same_when_testing() {
66            assert_eq!(Current::get_seed(), ZeroedTestSeed::get_seed());
67        }
68
69        #[test]
70        fn the_default_seed_and_the_instance_seed_should_be_different_when_testing() {
71            assert_ne!(Current::get_seed(), Instance::get_seed());
72        }
73    }
74
75    mod detail {
76        use crate::shared::crypto::ephemeral_instance_keys::Seed;
77
78        #[allow(dead_code)]
79        pub const ZEROED_TEST_SEED: &Seed = &[0u8; 32];
80
81        #[cfg(test)]
82        pub use ZEROED_TEST_SEED as CURRENT_SEED;
83
84        #[cfg(not(test))]
85        pub use crate::shared::crypto::ephemeral_instance_keys::RANDOM_SEED as CURRENT_SEED;
86
87        #[cfg(test)]
88        mod tests {
89            use crate::shared::crypto::ephemeral_instance_keys::RANDOM_SEED;
90            use crate::shared::crypto::keys::seeds::detail::ZEROED_TEST_SEED;
91            use crate::shared::crypto::keys::seeds::CURRENT_SEED;
92
93            #[test]
94            fn it_should_have_a_zero_test_seed() {
95                assert_eq!(*ZEROED_TEST_SEED, [0u8; 32]);
96            }
97
98            #[test]
99            fn it_should_default_to_zeroed_seed_when_testing() {
100                assert_eq!(*CURRENT_SEED, *ZEROED_TEST_SEED);
101            }
102
103            #[test]
104            fn it_should_have_a_large_random_seed() {
105                assert!(u128::from_ne_bytes((*RANDOM_SEED)[..16].try_into().unwrap()) > u128::from(u64::MAX));
106                assert!(u128::from_ne_bytes((*RANDOM_SEED)[16..].try_into().unwrap()) > u128::from(u64::MAX));
107            }
108        }
109    }
110}