Skip to main content

otplus_core/cipher/
root_key.rs

1use chacha20poly1305::{aead::{KeyInit, OsRng}, Key, ChaCha20Poly1305};
2use zeroize::Zeroize;
3use serde::{Serialize, Serializer, Deserialize, Deserializer};
4use serde::de::Error;
5use base64::{engine::general_purpose::STANDARD, Engine};
6use serde::ser::SerializeStruct;
7use chrono::Utc;
8
9#[derive(Debug, Clone)]
10pub struct RootKeyMetadata {
11    pub created_at: i64,
12    pub key_length: u32,
13}
14
15impl Serialize for RootKeyMetadata {
16    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17    where
18        S: Serializer,
19    {
20        let mut state = serializer.serialize_struct("RootKeyMetadata", 2)?;
21        state.serialize_field("created_at", &self.created_at)?;
22        state.serialize_field("key_length", &self.key_length)?;
23        state.end()
24    }
25}
26
27impl<'de> Deserialize<'de> for RootKeyMetadata {
28    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
29    where
30        D: Deserializer<'de>,
31    {
32        #[derive(Deserialize)]
33        struct RootKeyMetadataHelper {
34            created_at: i64,
35            key_length: u32,
36        }
37
38        let helper = RootKeyMetadataHelper::deserialize(deserializer)?;
39        Ok(Self { created_at: helper.created_at, key_length: helper.key_length })
40    }
41}
42
43#[derive(Debug, Clone)]
44pub struct RootKey {
45    pub value: Key,
46    pub metadata: RootKeyMetadata,
47}
48
49impl Serialize for RootKey {
50    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
51    where
52        S: Serializer,
53    {
54        let mut state = serializer.serialize_struct("RootKey", 2)?;
55        state.serialize_field("value", &STANDARD.encode(&self.value.as_slice()))?;
56        state.serialize_field("metadata", &self.metadata)?;
57        state.end()
58    }
59}
60
61impl<'de> Deserialize<'de> for RootKey {
62    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
63    where
64        D: Deserializer<'de>,
65    {
66        #[derive(Deserialize)]
67        struct RootKeyHelper {
68            value: String,
69            metadata: RootKeyMetadata,
70        }
71
72        let helper = RootKeyHelper::deserialize(deserializer)?;
73        let key = STANDARD.decode(&helper.value)
74            .map_err(|e| Error::custom(e.to_string()))?;
75        
76        if key.len() != 32 {
77            return Err(Error::custom("Invalid key length"));
78        }
79
80        Ok(Self { value: Key::from_slice(&key).clone(), metadata: helper.metadata })
81    }
82}
83
84impl Drop for RootKey {
85    fn drop(&mut self) {
86        self.value.as_mut_slice().zeroize();
87    }
88}
89
90impl Default for RootKey {
91    fn default() -> Self {
92        let mut os_rng = OsRng::default();
93        let value = ChaCha20Poly1305::generate_key(&mut os_rng);
94        Self { value, metadata: RootKeyMetadata { created_at: Utc::now().timestamp_millis(), key_length: 32 } }
95    }
96}
97
98#[cfg(test)]
99mod root_key_tests {
100    use super::*;
101
102    #[test]
103    fn test_data_key_default() {
104        let dek = RootKey::default();
105        assert_eq!(dek.value.as_slice().len(), 32);
106        assert_eq!(dek.metadata.key_length, 32);
107    }
108
109    #[test]
110    fn test_data_key_serialize_deserialize() {
111        let dek = RootKey::default();
112        let serialized = serde_json::to_string(&dek).unwrap();
113        println!("Serialized: {}", serialized);
114        let deserialized: RootKey = serde_json::from_str(&serialized).unwrap();
115        println!("Deserialized: {:?}", deserialized);
116    }
117}