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