libsignal_service/
master_key.rs1use rand::{CryptoRng, Rng};
2
3const MASTER_KEY_LEN: usize = 32;
4const STORAGE_KEY_LEN: usize = 32;
5
6#[derive(Debug, PartialEq)]
7pub struct MasterKey {
8 pub inner: [u8; MASTER_KEY_LEN],
9}
10
11impl MasterKey {
12 pub fn generate<R: Rng + CryptoRng>(csprng: &mut R) -> Self {
13 let mut inner = [0_u8; MASTER_KEY_LEN];
15 csprng.fill(&mut inner);
16 Self { inner }
17 }
18
19 pub fn from_slice(
20 slice: &[u8],
21 ) -> Result<Self, std::array::TryFromSliceError> {
22 let inner = slice.try_into()?;
23 Ok(Self { inner })
24 }
25}
26
27impl From<MasterKey> for Vec<u8> {
28 fn from(val: MasterKey) -> Self {
29 val.inner.to_vec()
30 }
31}
32
33#[derive(Debug, PartialEq)]
34pub struct StorageServiceKey {
35 pub inner: [u8; STORAGE_KEY_LEN],
36}
37
38impl StorageServiceKey {
39 pub fn from_master_key(master_key: &MasterKey) -> Self {
40 use hmac::{Hmac, Mac};
41 use sha2::Sha256;
42
43 type HmacSha256 = Hmac<Sha256>;
44 const KEY: &[u8] = b"Storage Service Encryption";
45
46 let mut mac = HmacSha256::new_from_slice(&master_key.inner).unwrap();
47 mac.update(KEY);
48 let result = mac.finalize();
49 let inner: [u8; STORAGE_KEY_LEN] = result.into_bytes().into();
50
51 Self { inner }
52 }
53
54 pub fn from_slice(
55 slice: &[u8],
56 ) -> Result<Self, std::array::TryFromSliceError> {
57 let inner = slice.try_into()?;
58 Ok(Self { inner })
59 }
60}
61
62impl From<StorageServiceKey> for Vec<u8> {
63 fn from(val: StorageServiceKey) -> Self {
64 val.inner.to_vec()
65 }
66}
67
68pub trait MasterKeyStore {
70 fn fetch_master_key(&self) -> Option<MasterKey>;
72
73 fn fetch_storage_service_key(&self) -> Option<StorageServiceKey>;
75
76 fn store_master_key(&self, master_key: Option<&MasterKey>);
78
79 fn store_storage_service_key(
81 &self,
82 storage_key: Option<&StorageServiceKey>,
83 );
84}
85
86mod tests {
87 #[test]
88 fn derive_storage_key_from_master_key() {
89 use super::{MasterKey, StorageServiceKey};
90 use base64::prelude::*;
91
92 let master_key_bytes = BASE64_STANDARD
96 .decode("9hquLIIZmom8fHF7H8pbUAreawmPLEqli5ceJ94pFkU=")
97 .unwrap();
98 let storage_key_bytes = BASE64_STANDARD
99 .decode("QMgZ5RGTLFTr4u/J6nypaJX6DKDlSgMw8vmxU6gxnvI=")
100 .unwrap();
101 assert_eq!(master_key_bytes.len(), 32);
102 assert_eq!(storage_key_bytes.len(), 32);
103
104 let master_key = MasterKey::from_slice(&master_key_bytes).unwrap();
105 let storage_key = StorageServiceKey::from_master_key(&master_key);
106
107 assert_eq!(master_key.inner, master_key_bytes.as_slice());
108 assert_eq!(storage_key.inner, storage_key_bytes.as_slice());
109 }
110}