reddb_server/storage/encryption/
header.rs1use super::key::SecureKey;
16use super::page_encryptor::PageEncryptor;
17use crate::crypto::uuid::Uuid;
18
19pub use reddb_file::{
20 PAGED_ENCRYPTION_KEY_CHECK_PLAINTEXT_SIZE as KEY_CHECK_LEN,
21 PAGED_ENCRYPTION_SALT_SIZE as SALT_SIZE,
22};
23
24#[derive(Debug, Clone)]
26pub struct EncryptionHeader {
27 pub salt: [u8; SALT_SIZE],
29
30 pub key_check: Vec<u8>,
34}
35
36impl EncryptionHeader {
37 pub fn new(key: &SecureKey) -> Self {
39 let uuid = Uuid::new_v4();
41 let mut salt = [0u8; SALT_SIZE];
42 let b = uuid.as_bytes();
44 salt[0..16].copy_from_slice(b);
45 let uuid2 = Uuid::new_v4();
46 salt[16..32].copy_from_slice(uuid2.as_bytes());
47
48 let known_value = [0xAAu8; KEY_CHECK_LEN];
51 let encryptor = PageEncryptor::new(key.clone());
52
53 let check_blob = encryptor.encrypt(u32::MAX, &known_value);
55
56 Self {
57 salt,
58 key_check: check_blob,
59 }
60 }
61
62 pub fn validate(&self, key: &SecureKey) -> bool {
64 let encryptor = PageEncryptor::new(key.clone());
65
66 match encryptor.decrypt(u32::MAX, &self.key_check) {
67 Ok(plaintext) => {
68 let expected = [0xAAu8; KEY_CHECK_LEN];
69 plaintext == expected
70 }
71 Err(_) => false,
72 }
73 }
74
75 pub fn to_bytes(&self) -> Vec<u8> {
77 reddb_file::encode_paged_encryption_header(&reddb_file::PagedEncryptionHeader {
78 salt: self.salt,
79 key_check: self.key_check.clone(),
80 })
81 }
82
83 pub fn from_bytes(data: &[u8]) -> Result<Self, String> {
85 let raw = reddb_file::decode_paged_encryption_header(data)
86 .map_err(|err| format!("Data too short for EncryptionHeader: {err}"))?;
87 Ok(Self {
88 salt: raw.salt,
89 key_check: raw.key_check,
90 })
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_header_validation() {
100 let key = SecureKey::new(&[0x11u8; 32]);
101 let header = EncryptionHeader::new(&key);
102
103 assert!(header.validate(&key));
104
105 let wrong_key = SecureKey::new(&[0x22u8; 32]);
106 assert!(!header.validate(&wrong_key));
107 }
108
109 #[test]
110 fn test_header_serialization() {
111 let key = SecureKey::new(&[0x33u8; 32]);
112 let header = EncryptionHeader::new(&key);
113
114 let bytes = header.to_bytes();
115 let loaded = EncryptionHeader::from_bytes(&bytes).unwrap();
116
117 assert_eq!(header.salt, loaded.salt);
118 assert_eq!(header.key_check, loaded.key_check);
119 assert!(loaded.validate(&key));
120 }
121}