Rust · 7093 bytes Raw Blame History
1 //! # ZephyrFS Cryptography Module
2 //!
3 //! Provides zero-knowledge client-side encryption for ZephyrFS distributed storage.
4 //! Implements Tahoe-LAFS inspired capability-based security with mandatory encryption.
5 //!
6 //! ## Architecture
7 //! - AES-256-GCM encryption for file segments
8 //! - Scrypt key derivation from user passwords
9 //! - Hierarchical deterministic keys for per-segment encryption
10 //! - Secure memory handling with automatic cleanup
11 //! - Content addressing with cryptographic verification
12
13 pub mod encryption;
14 pub mod key_derivation;
15 pub mod secure_memory;
16 pub mod content_addressing;
17
18 pub use encryption::{FileEncryption, SegmentEncryption, EncryptedData};
19 pub use key_derivation::{KeyDerivation, DerivedKey, KeyHierarchy};
20 pub use secure_memory::{SecureBytes, SecureString};
21 pub use content_addressing::{ContentId, ContentVerifier, HashAlgorithm};
22
23 use anyhow::Result;
24 use zeroize::Zeroize;
25
26 /// Core cryptographic parameters following Tahoe-LAFS security model
27 pub struct CryptoParams {
28 /// Scrypt parameters: N=2^17, r=8, p=1, output=96 bytes
29 pub scrypt_params: ScryptParams,
30 /// AES-256-GCM parameters
31 pub aes_params: AesParams,
32 /// Content addressing parameters
33 pub hash_params: HashParams,
34 }
35
36 #[derive(Debug, Clone)]
37 pub struct ScryptParams {
38 pub log_n: u8, // 17 (N = 2^17 = 131072)
39 pub r: u32, // 8
40 pub p: u32, // 1
41 pub output_len: usize, // 96 bytes (master key + salt + verification)
42 }
43
44 #[derive(Debug, Clone)]
45 pub struct AesParams {
46 pub key_len: usize, // 32 bytes (AES-256)
47 pub nonce_len: usize, // 12 bytes (GCM standard)
48 pub tag_len: usize, // 16 bytes (GCM authentication tag)
49 }
50
51 #[derive(Debug, Clone)]
52 pub struct HashParams {
53 pub content_hasher: ContentHasher,
54 pub verification_hasher: VerificationHasher,
55 }
56
57 #[derive(Debug, Clone)]
58 pub enum ContentHasher {
59 Blake3, // Fast hashing for content IDs
60 Sha256, // SHA-256 for compatibility
61 }
62
63 #[derive(Debug, Clone)]
64 pub enum VerificationHasher {
65 Blake3, // Fast verification
66 Sha256, // Standard verification
67 }
68
69 impl Default for CryptoParams {
70 fn default() -> Self {
71 Self {
72 scrypt_params: ScryptParams {
73 log_n: 17, // 2^17 iterations (strong security)
74 r: 8, // Memory cost parameter
75 p: 1, // Parallelization parameter
76 output_len: 64, // 64 bytes (max supported by scrypt crate)
77 },
78 aes_params: AesParams {
79 key_len: 32, // AES-256
80 nonce_len: 12, // GCM standard nonce size
81 tag_len: 16, // GCM authentication tag size
82 },
83 hash_params: HashParams {
84 content_hasher: ContentHasher::Blake3,
85 verification_hasher: VerificationHasher::Blake3,
86 },
87 }
88 }
89 }
90
91 /// High-level cryptographic operations for ZephyrFS
92 pub struct ZephyrCrypto {
93 params: CryptoParams,
94 key_hierarchy: Option<KeyHierarchy>,
95 }
96
97 impl ZephyrCrypto {
98 /// Create new crypto instance with default parameters
99 pub fn new() -> Self {
100 Self {
101 params: CryptoParams::default(),
102 key_hierarchy: None,
103 }
104 }
105
106 /// Create crypto instance with custom parameters
107 pub fn with_params(params: CryptoParams) -> Self {
108 Self {
109 params,
110 key_hierarchy: None,
111 }
112 }
113
114 /// Initialize key hierarchy from password
115 pub fn init_from_password(&mut self, password: &str) -> Result<()> {
116 let key_derivation = KeyDerivation::new(&self.params.scrypt_params);
117 let derived_key = key_derivation.derive_from_password(password)?;
118 self.key_hierarchy = Some(KeyHierarchy::new(derived_key)?);
119 Ok(())
120 }
121
122 /// Initialize key hierarchy from existing key material
123 pub fn init_from_key(&mut self, key_material: SecureBytes) -> Result<()> {
124 let derived_key = DerivedKey::from_bytes(key_material)?;
125 self.key_hierarchy = Some(KeyHierarchy::new(derived_key)?);
126 Ok(())
127 }
128
129 /// Encrypt file data into segments
130 pub fn encrypt_file(&self, file_data: &[u8]) -> Result<Vec<EncryptedData>> {
131 let hierarchy = self.key_hierarchy.as_ref()
132 .ok_or_else(|| anyhow::anyhow!("Key hierarchy not initialized"))?;
133
134 let file_encryption = FileEncryption::new(&self.params.aes_params);
135 file_encryption.encrypt_to_segments(file_data, hierarchy)
136 }
137
138 /// Decrypt file segments back to original data
139 pub fn decrypt_file(&self, encrypted_segments: &[EncryptedData]) -> Result<Vec<u8>> {
140 let hierarchy = self.key_hierarchy.as_ref()
141 .ok_or_else(|| anyhow::anyhow!("Key hierarchy not initialized"))?;
142
143 let file_encryption = FileEncryption::new(&self.params.aes_params);
144 file_encryption.decrypt_from_segments(encrypted_segments, hierarchy)
145 }
146
147 /// Generate content ID for data
148 pub fn content_id(&self, data: &[u8]) -> ContentId {
149 ContentId::generate(data, &self.params.hash_params.content_hasher)
150 }
151
152 /// Verify content integrity
153 pub fn verify_content(&self, data: &[u8], expected_id: &ContentId) -> bool {
154 ContentVerifier::verify(data, expected_id, &self.params.hash_params.verification_hasher)
155 }
156
157 /// Get public key material for capability sharing (zero-knowledge proof)
158 pub fn get_capability(&self) -> Result<Vec<u8>> {
159 let hierarchy = self.key_hierarchy.as_ref()
160 .ok_or_else(|| anyhow::anyhow!("Key hierarchy not initialized"))?;
161
162 // Return only public/shareable key material, never private keys
163 Ok(hierarchy.get_public_capability()?)
164 }
165 }
166
167 impl Drop for ZephyrCrypto {
168 fn drop(&mut self) {
169 // Ensure all sensitive data is cleared when dropping
170 if let Some(ref mut hierarchy) = self.key_hierarchy {
171 hierarchy.zeroize();
172 }
173 }
174 }
175
176 impl Zeroize for ZephyrCrypto {
177 fn zeroize(&mut self) {
178 if let Some(ref mut hierarchy) = self.key_hierarchy {
179 hierarchy.zeroize();
180 }
181 self.key_hierarchy = None;
182 }
183 }
184
185 #[cfg(test)]
186 mod tests {
187 use super::*;
188
189 #[test]
190 fn test_crypto_params_default() {
191 let params = CryptoParams::default();
192 assert_eq!(params.scrypt_params.log_n, 17);
193 assert_eq!(params.scrypt_params.r, 8);
194 assert_eq!(params.scrypt_params.p, 1);
195 assert_eq!(params.aes_params.key_len, 32);
196 assert_eq!(params.aes_params.nonce_len, 12);
197 assert_eq!(params.aes_params.tag_len, 16);
198 }
199
200 #[test]
201 fn test_zephyr_crypto_creation() {
202 let crypto = ZephyrCrypto::new();
203 assert!(crypto.key_hierarchy.is_none());
204 }
205
206 #[test]
207 fn test_crypto_init_from_password() {
208 let mut crypto = ZephyrCrypto::new();
209 let result = crypto.init_from_password("test_password_123");
210 assert!(result.is_ok());
211 assert!(crypto.key_hierarchy.is_some());
212 }
213 }