1use crate::dht::{DHT, Key};
7use crate::identity::enhanced::{EnhancedIdentity, DeviceId};
8use serde::{Deserialize, Serialize};
9use std::time::{SystemTime, Duration};
10use thiserror::Error;
11use aes_gcm::{
12 aead::{Aead, KeyInit},
13 Aes256Gcm, Nonce, Key as AesKey,
14};
15use sha2::{Sha256, Digest};
16
17#[derive(Debug, Error)]
19pub enum StorageError {
20 #[error("DHT error: {0}")]
21 DhtError(String),
22
23 #[error("Encryption error: {0}")]
24 EncryptionError(String),
25
26 #[error("Serialization error: {0}")]
27 SerializationError(#[from] bincode::Error),
28
29 #[error("Key not found: {0}")]
30 KeyNotFound(String),
31
32 #[error("Invalid data format")]
33 InvalidFormat,
34}
35
36type Result<T> = std::result::Result<T, StorageError>;
37
38pub mod keys {
40 pub fn profile(user_id: &str) -> String {
42 format!("profile:{}", user_id)
43 }
44
45 pub fn devices(user_id: &str) -> String {
47 format!("devices:{}", user_id)
48 }
49
50 pub fn chat_channel(channel_id: &str) -> String {
52 format!("chat:channel:{}", channel_id)
53 }
54
55 pub fn chat_message(channel_id: &str, msg_id: &str) -> String {
57 format!("chat:msg:{}:{}", channel_id, msg_id)
58 }
59
60 pub fn chat_index(channel_id: &str, timestamp: u64) -> String {
62 format!("chat:idx:{}:{}", channel_id, timestamp)
63 }
64
65 pub fn discuss_topic(topic_id: &str) -> String {
67 format!("discuss:topic:{}", topic_id)
68 }
69
70 pub fn discuss_reply(topic_id: &str, reply_id: &str) -> String {
72 format!("discuss:reply:{}:{}", topic_id, reply_id)
73 }
74
75 pub fn project(project_id: &str) -> String {
77 format!("project:{}", project_id)
78 }
79
80 pub fn document_meta(doc_id: &str) -> String {
82 format!("doc:meta:{}", doc_id)
83 }
84
85 pub fn file_chunk(file_id: &str, chunk_num: u32) -> String {
87 format!("file:chunk:{}:{:08}", file_id, chunk_num)
88 }
89
90 pub fn organization(org_id: &str) -> String {
92 format!("org:{}", org_id)
93 }
94
95 pub fn public_channel_list() -> String {
97 "public:channels".to_string()
98 }
99
100 pub fn user_channels(user_id: &str) -> String {
102 format!("user:channels:{}", user_id)
103 }
104}
105
106pub mod ttl {
108 use std::time::Duration;
109
110 pub const PROFILE: Duration = Duration::from_secs(365 * 24 * 60 * 60); pub const MESSAGE: Duration = Duration::from_secs(90 * 24 * 60 * 60); pub const FILE_CHUNK: Duration = Duration::from_secs(365 * 24 * 60 * 60); pub const TEMP: Duration = Duration::from_secs(24 * 60 * 60); pub const PRESENCE: Duration = Duration::from_secs(5 * 60); }
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct EncryptedData {
129 pub ciphertext: Vec<u8>,
131
132 pub nonce: Vec<u8>,
134
135 pub key_id: String,
137
138 pub timestamp: SystemTime,
140
141 pub metadata: Option<serde_json::Value>,
143}
144
145pub struct StorageManager {
147 dht: DHT,
149
150 master_key: [u8; 32],
152}
153
154impl StorageManager {
155 pub fn new(dht: DHT, identity: &EnhancedIdentity) -> Result<Self> {
157 let mut hasher = Sha256::new();
159 hasher.update(identity.base_identity.user_id.as_bytes()); let master_key: [u8; 32] = hasher.finalize().into();
161
162 Ok(Self {
163 dht,
164 master_key,
165 })
166 }
167
168 pub async fn store_encrypted<T: Serialize>(
170 &mut self,
171 key: &str,
172 data: &T,
173 ttl: Duration,
174 metadata: Option<serde_json::Value>,
175 ) -> Result<()> {
176 let plaintext = bincode::serialize(data)?;
178
179 let encrypted = self.encrypt(&plaintext)?;
181
182 let wrapper = EncryptedData {
184 ciphertext: encrypted.0,
185 nonce: encrypted.1.to_vec(),
186 key_id: "v1".to_string(),
187 timestamp: SystemTime::now(),
188 metadata,
189 };
190
191 let wrapper_bytes = bincode::serialize(&wrapper)?;
193
194 let dht_key = Key::new(key.as_bytes());
196
197 self.dht.put(dht_key, wrapper_bytes).await
198 .map_err(|e| StorageError::DhtError(e.to_string()))?;
199
200 Ok(())
201 }
202
203 pub async fn get_encrypted<T: for<'de> Deserialize<'de>>(
205 &self,
206 key: &str,
207 ) -> Result<T> {
208 let dht_key = Key::new(key.as_bytes());
210 let record = self.dht.get(&dht_key).await
211 .ok_or_else(|| StorageError::KeyNotFound(key.to_string()))?;
212
213 let wrapper: EncryptedData = bincode::deserialize(&record.value)?;
215
216 let plaintext = self.decrypt(&wrapper.ciphertext, &wrapper.nonce)?;
218
219 let data = bincode::deserialize(&plaintext)?;
221
222 Ok(data)
223 }
224
225 pub async fn store_public<T: Serialize>(
227 &mut self,
228 key: &str,
229 data: &T,
230 ttl: Duration,
231 ) -> Result<()> {
232 let value = bincode::serialize(data)?;
233
234 let dht_key = Key::new(key.as_bytes());
235
236 self.dht.put(dht_key, value).await
237 .map_err(|e| StorageError::DhtError(e.to_string()))?;
238
239 Ok(())
240 }
241
242 pub async fn get_public<T: for<'de> Deserialize<'de>>(
244 &self,
245 key: &str,
246 ) -> Result<T> {
247 let dht_key = Key::new(key.as_bytes());
248 let record = self.dht.get(&dht_key).await
249 .ok_or_else(|| StorageError::KeyNotFound(key.to_string()))?;
250
251 let data = bincode::deserialize(&record.value)?;
252 Ok(data)
253 }
254
255 pub async fn delete(&mut self, key: &str) -> Result<()> {
257 let dht_key = Key::new(key.as_bytes());
259 self.dht.put(dht_key, vec![]).await
260 .map_err(|e| StorageError::DhtError(e.to_string()))?;
261 Ok(())
262 }
263
264 pub async fn list_keys(&self, prefix: &str) -> Result<Vec<String>> {
266 Ok(vec![])
269 }
270
271 fn encrypt(&self, plaintext: &[u8]) -> Result<(Vec<u8>, [u8; 12])> {
273 let cipher = Aes256Gcm::new(AesKey::<Aes256Gcm>::from_slice(&self.master_key));
274
275 let nonce_bytes = rand::random::<[u8; 12]>();
277 let nonce = Nonce::from_slice(&nonce_bytes);
278
279 let ciphertext = cipher.encrypt(nonce, plaintext)
280 .map_err(|e| StorageError::EncryptionError(e.to_string()))?;
281
282 Ok((ciphertext, nonce_bytes))
283 }
284
285 fn decrypt(&self, ciphertext: &[u8], nonce: &[u8]) -> Result<Vec<u8>> {
287 let cipher = Aes256Gcm::new(AesKey::<Aes256Gcm>::from_slice(&self.master_key));
288 let nonce = Nonce::from_slice(nonce);
289
290 let plaintext = cipher.decrypt(nonce, ciphertext)
291 .map_err(|e| StorageError::EncryptionError(e.to_string()))?;
292
293 Ok(plaintext)
294 }
295}
296
297pub struct FileChunker {
375 chunk_size: usize,
376}
377
378impl FileChunker {
379 pub fn new(chunk_size: usize) -> Self {
381 Self { chunk_size }
382 }
383
384 pub fn chunk_file(&self, data: &[u8]) -> Vec<Vec<u8>> {
386 data.chunks(self.chunk_size)
387 .map(|chunk| chunk.to_vec())
388 .collect()
389 }
390
391 pub async fn store_file(
393 &self,
394 storage: &mut StorageManager,
395 file_id: &str,
396 data: &[u8],
397 metadata: FileMetadata,
398 ) -> Result<()> {
399 let chunks = self.chunk_file(data);
400 let total_chunks = chunks.len() as u32;
401
402 let meta_with_chunks = FileMetadata {
404 total_chunks,
405 ..metadata
406 };
407
408 let meta_key = keys::document_meta(file_id);
409 storage.store_encrypted(
410 &meta_key,
411 &meta_with_chunks,
412 ttl::FILE_CHUNK,
413 None,
414 ).await?;
415
416 for (i, chunk) in chunks.iter().enumerate() {
418 let chunk_key = keys::file_chunk(file_id, i as u32);
419 storage.store_encrypted(
420 &chunk_key,
421 chunk,
422 ttl::FILE_CHUNK,
423 None,
424 ).await?;
425 }
426
427 Ok(())
428 }
429
430 pub async fn get_file(
432 &self,
433 storage: &StorageManager,
434 file_id: &str,
435 ) -> Result<Vec<u8>> {
436 let meta_key = keys::document_meta(file_id);
438 let metadata: FileMetadata = storage.get_encrypted(&meta_key).await?;
439
440 let mut data = Vec::new();
442 for i in 0..metadata.total_chunks {
443 let chunk_key = keys::file_chunk(file_id, i);
444 let chunk: Vec<u8> = storage.get_encrypted(&chunk_key).await?;
445 data.extend(chunk);
446 }
447
448 Ok(data)
449 }
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct FileMetadata {
455 pub file_id: String,
456 pub name: String,
457 pub size: u64,
458 pub mime_type: String,
459 pub hash: Vec<u8>,
460 pub total_chunks: u32,
461 pub created_at: SystemTime,
462 pub created_by: String,
463}