reddb_server/storage/encryption/
page_encryptor.rs1use super::key::SecureKey;
15
16pub const NONCE_SIZE: usize = reddb_crypto::NONCE_SIZE;
18pub const TAG_SIZE: usize = reddb_crypto::TAG_SIZE;
20pub const OVERHEAD: usize = reddb_crypto::PAGE_ENVELOPE_OVERHEAD;
22
23pub struct PageEncryptor {
25 key: SecureKey,
26}
27
28impl PageEncryptor {
29 pub fn new(key: SecureKey) -> Self {
31 Self { key }
32 }
33
34 pub fn encrypt(&self, page_id: u32, plaintext: &[u8]) -> Vec<u8> {
41 reddb_crypto::encrypt_page(self.key_bytes(), page_id, plaintext)
42 .expect("page envelope encryption failed (CSPRNG)")
43 }
44
45 pub fn decrypt(&self, page_id: u32, encrypted_data: &[u8]) -> Result<Vec<u8>, String> {
47 reddb_crypto::decrypt_page(self.key_bytes(), page_id, encrypted_data)
48 .map_err(|e| e.to_string())
49 }
50
51 fn key_bytes(&self) -> &[u8; 32] {
52 self.key
53 .as_bytes()
54 .try_into()
55 .expect("Key must be 32 bytes")
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_page_encryption_roundtrip() {
65 let key = SecureKey::new(&[0x42u8; 32]);
66 let encryptor = PageEncryptor::new(key);
67
68 let page_id = 123;
69 let plaintext = b"This is a secret page content.";
70
71 let encrypted = encryptor.encrypt(page_id, plaintext);
72
73 assert_eq!(encrypted.len(), plaintext.len() + OVERHEAD);
75
76 let decrypted = encryptor.decrypt(page_id, &encrypted).unwrap();
78 assert_eq!(decrypted, plaintext);
79 }
80
81 #[test]
82 fn test_page_encryption_bad_page_id() {
83 let key = SecureKey::new(&[0x42u8; 32]);
84 let encryptor = PageEncryptor::new(key);
85
86 let plaintext = b"content";
87 let encrypted = encryptor.encrypt(100, plaintext);
88
89 let result = encryptor.decrypt(101, &encrypted);
91 assert!(result.is_err());
92 }
93
94 #[test]
95 fn test_page_encryption_tampering() {
96 let key = SecureKey::new(&[0x42u8; 32]);
97 let encryptor = PageEncryptor::new(key);
98
99 let plaintext = b"content";
100 let mut encrypted = encryptor.encrypt(100, plaintext);
101
102 let last = encrypted.len() - 1;
104 encrypted[last] ^= 1;
105
106 let result = encryptor.decrypt(100, &encrypted);
107 assert!(result.is_err());
108 }
109}