From 6abd836bddf754dfb71fe9c841e77246c917e8b3 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 06:55:27 +0300 Subject: [PATCH 01/24] feat: adaugat structura de baza pentru ipfs_plugin --- Cargo.lock | 6 +++--- src/ipfs_plugin.rs | 13 +++++++++++++ src/lib.rs | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/ipfs_plugin.rs diff --git a/Cargo.lock b/Cargo.lock index 8d2d0a9e..990ffbef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,7 +195,7 @@ dependencies = [ "log", "parking", "polling 2.8.0", - "rustix 0.37.27", + "rustix 0.37.28", "slab", "socket2 0.4.10", "waker-fn", @@ -1953,9 +1953,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" +version = "0.37.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" dependencies = [ "bitflags 1.3.2", "errno", diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs new file mode 100644 index 00000000..70b7363b --- /dev/null +++ b/src/ipfs_plugin.rs @@ -0,0 +1,13 @@ +pub struct IpfsCipher { + // Stocăm cheia de criptare mai târziu +} + +impl IpfsCipher { + pub fn new() -> Self { + Self {} + } + + pub fn encrypt(&self, data: &[u8]) -> Result, String> { + Ok(data.to_vec()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 22657c91..5cdf2ae8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -326,3 +326,5 @@ pub const fn is_debug() -> bool { } false } + +pub mod ipfs_plugin; From 29c1c5edebc22bc7527a2cacc508f5ee555a2634 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:18:11 +0300 Subject: [PATCH 02/24] chore: adaugat importurile necesare pentru criptare si manipulare stream-uri --- src/ipfs_plugin.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 70b7363b..1b543206 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -1,13 +1,4 @@ -pub struct IpfsCipher { - // Stocăm cheia de criptare mai târziu -} - -impl IpfsCipher { - pub fn new() -> Self { - Self {} - } - - pub fn encrypt(&self, data: &[u8]) -> Result, String> { - Ok(data.to_vec()) - } -} +use crate::crypto::{self, Cipher}; +use crate::crypto::write::CryptoWrite; // Rezolvă eroarea cu .finish() +use shush_rs::SecretVec; +use std::io::{Read, Write, Cursor}; \ No newline at end of file From cb3572e3dedd52ed57d73006a8af05ebef298358 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:18:50 +0300 Subject: [PATCH 03/24] feat: definit structura de date IpfsCipher cu campurile pentru cheie si algoritm --- src/ipfs_plugin.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 1b543206..1bc62fa3 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -1,4 +1,9 @@ use crate::crypto::{self, Cipher}; use crate::crypto::write::CryptoWrite; // Rezolvă eroarea cu .finish() use shush_rs::SecretVec; -use std::io::{Read, Write, Cursor}; \ No newline at end of file +use std::io::{Read, Write, Cursor}; + +pub struct IpfsCipher { + key: SecretVec, + cipher: Cipher, +} From f2bd2b59256937d2b982d7cc99f263d429d0721f Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:24:53 +0300 Subject: [PATCH 04/24] feat: adaugat semnatura functiei de initializare pentru IpfsCipher --- src/ipfs_plugin.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 1bc62fa3..d5819436 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -7,3 +7,11 @@ pub struct IpfsCipher { key: SecretVec, cipher: Cipher, } + +impl IpfsCipher { + /// Inițializează plugin-ul cu o cheie sigură și cipher-ul implicit + pub fn new(secret_key: Vec) -> Self { + + } + +} \ No newline at end of file From 12db0781da854106b004f287ffcba959f7614ec4 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:25:34 +0300 Subject: [PATCH 05/24] feat: implementat instantierea corecta a cheii secrete si setarea cifrului implicit --- src/ipfs_plugin.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index d5819436..fdcdd524 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -11,7 +11,10 @@ pub struct IpfsCipher { impl IpfsCipher { /// Inițializează plugin-ul cu o cheie sigură și cipher-ul implicit pub fn new(secret_key: Vec) -> Self { - + Self { + key: SecretVec::from(secret_key), + cipher: Cipher::ChaCha20Poly1305, + } } } \ No newline at end of file From b3a0ae89baf1207f769222e554a78598486ef340 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:29:05 +0300 Subject: [PATCH 06/24] feat: definit semnatura encrypt si adaugat tratarea cazului pentru date goale --- src/ipfs_plugin.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index fdcdd524..48e15aa8 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -17,4 +17,12 @@ impl IpfsCipher { } } + /// Criptează un bloc de date utilizând un Cursor pentru a simula un fișier în memorie + pub fn encrypt(&self, data: &[u8]) -> Result, String> { + if data.is_empty() { + return Ok(Vec::new()); + } + + + } } \ No newline at end of file From 8f2ac30d0c03b48398bae3e30b6eb88ab491c915 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:31:59 +0300 Subject: [PATCH 07/24] feat: initializat Cursor in memorie si instantiat RingCryptoWrite --- src/ipfs_plugin.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 48e15aa8..d9b55a8b 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -23,6 +23,11 @@ impl IpfsCipher { return Ok(Vec::new()); } + // Folosim Cursor pentru a implementa Write + Seek + Read cerute de autor + let memory_file = Cursor::new(Vec::new()); + let mut writer = crypto::create_write(memory_file, self.cipher, &self.key); + writer.write_all(data) + .map_err(|e| format!("Eroare la scrierea datelor IPFS: {:?}", e))?; } } \ No newline at end of file From bfa24f2c65c0778e9123c399cb94d25b6546a590 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:33:08 +0300 Subject: [PATCH 08/24] feat: finalizat procesul de scriere criptata si extragerea blocului de bytes final --- src/ipfs_plugin.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index d9b55a8b..56f4edda 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -29,5 +29,12 @@ impl IpfsCipher { writer.write_all(data) .map_err(|e| format!("Eroare la scrierea datelor IPFS: {:?}", e))?; + + // .finish() returnează obiectul intern (Cursor-ul) în caz de succes + let finished_cursor = writer.finish() + .map_err(|e| format!("Eroare la finalizarea criptării IPFS: {:?}", e))?; + + // Extriem vectorul de bytes din interiorul cursorului + Ok(finished_cursor.into_inner()) } } \ No newline at end of file From a68daaff6fafb28e885f7f37685d395dc6490b69 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:36:31 +0300 Subject: [PATCH 09/24] feat: definit semnatura decrypt si validarea initiala a buffer-ului --- src/ipfs_plugin.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 56f4edda..1b4c703e 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -37,4 +37,13 @@ impl IpfsCipher { // Extriem vectorul de bytes din interiorul cursorului Ok(finished_cursor.into_inner()) } + + /// Decriptează un bloc de date utilizând CryptoRead-ul nativ din rencfs + pub fn decrypt(&self, encrypted_data: &[u8]) -> Result, String> { + if encrypted_data.is_empty() { + return Ok(Vec::new()); + } + + + } } \ No newline at end of file From 7c130eed22e4651b61f97b82695f0026a41f1d5c Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:36:58 +0300 Subject: [PATCH 10/24] feat: finalizat logica de decriptare nativa utilizand RingCryptoRead --- src/ipfs_plugin.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 1b4c703e..127dd48f 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -44,6 +44,12 @@ impl IpfsCipher { return Ok(Vec::new()); } - + let mut reader = crypto::create_read(encrypted_data, self.cipher, &self.key); + let mut decrypted_data = Vec::new(); + + reader.read_to_end(&mut decrypted_data) + .map_err(|e| format!("Eroare la decriptarea datelor IPFS: {:?}", e))?; + + Ok(decrypted_data) } } \ No newline at end of file From f6f579b6bf574d100e7f49a61813e7cedd3f54d8 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:40:23 +0300 Subject: [PATCH 11/24] test: configurat modulul de teste unitare izolate pentru plugin --- src/ipfs_plugin.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 127dd48f..7430f84f 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -52,4 +52,12 @@ impl IpfsCipher { Ok(decrypted_data) } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + } \ No newline at end of file From eeb8772e04d33844a45b50835f02adca7625af5e Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:41:09 +0300 Subject: [PATCH 12/24] test: initializat datele mock si cheia de 32 de bytes --- src/ipfs_plugin.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index 7430f84f..f8f9848c 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -59,5 +59,12 @@ mod tests { use super::*; #[test] - + fn test_ipfs_encryption_decryption() { + // Generăm o cheie de test de 32 de bytes (pentru ChaCha20Poly1305) + let test_key = vec![0u8; 32]; + let cipher = IpfsCipher::new(test_key); + + let original_data = b"Date secrete trimise prin IPFS cu CID unic!"; + + } } \ No newline at end of file From 02f03644b80e6899053a6ec20ab18213425238be Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:41:32 +0300 Subject: [PATCH 13/24] test: adaugat verificarile finale pentru a valida fluxul complet --- src/ipfs_plugin.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ipfs_plugin.rs b/src/ipfs_plugin.rs index f8f9848c..d283a77c 100644 --- a/src/ipfs_plugin.rs +++ b/src/ipfs_plugin.rs @@ -66,5 +66,12 @@ mod tests { let original_data = b"Date secrete trimise prin IPFS cu CID unic!"; + // 1. Criptăm datele + let encrypted = cipher.encrypt(original_data).expect("Criptarea a eșuat"); + assert_ne!(original_data.to_vec(), encrypted, "Datele criptate nu trebuie să fie la fel ca cele originale"); + + // 2. Decriptăm datele înapoi + let decrypted = cipher.decrypt(&encrypted).expect("Decriptarea a eșuat"); + assert_eq!(original_data.to_vec(), decrypted, "Datele decriptate nu se potrivesc cu cele originale"); } } \ No newline at end of file From 387034ec62f379028f652c887b3e6cf7732f0013 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 08:48:52 +0300 Subject: [PATCH 14/24] feat: integrat IpfsCipher ca camp optional in structura principala EncryptedFs --- src/encryptedfs.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index 7c2da5a4..b6adade3 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -1,3 +1,4 @@ +use crate::ipfs_plugin::IpfsCipher; use argon2::password_hash::rand_core::RngCore; use async_trait::async_trait; use futures_util::TryStreamExt; @@ -574,6 +575,7 @@ pub struct EncryptedFs { sizes_read: Mutex>, requested_read: Mutex>, read_only: bool, + pub ipfs_cipher: Option, } impl EncryptedFs { @@ -627,6 +629,7 @@ impl EncryptedFs { sizes_read: Mutex::default(), requested_read: Mutex::default(), read_only, + ipfs_cipher: None, }; let arc = Arc::new(fs); @@ -638,6 +641,8 @@ impl EncryptedFs { arc.ensure_root_exists().await?; Ok(arc) + + } pub fn exists(&self, ino: u64) -> bool { @@ -2462,6 +2467,9 @@ impl EncryptedFs { return ino; } } + pub fn enable_ipfs_plugin(&mut self, master_key: Vec) { + self.ipfs_cipher = Some(IpfsCipher::new(master_key)); + } } pub struct CopyFileRangeReq { src_ino: u64, From 23d95a00fbb5d95c403937fbdd97ef2599b5709c Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Wed, 8 Jul 2026 13:37:45 +0300 Subject: [PATCH 15/24] chore: mutat ipfs_plugin in folder dedicat in root conform cerintelor de structura --- src/ipfs_plugin.rs => ipfs_plugin/src/lib.rs | 0 src/lib.rs | 1 + 2 files changed, 1 insertion(+) rename src/ipfs_plugin.rs => ipfs_plugin/src/lib.rs (100%) diff --git a/src/ipfs_plugin.rs b/ipfs_plugin/src/lib.rs similarity index 100% rename from src/ipfs_plugin.rs rename to ipfs_plugin/src/lib.rs diff --git a/src/lib.rs b/src/lib.rs index 5cdf2ae8..e29d075f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -327,4 +327,5 @@ pub const fn is_debug() -> bool { false } +#[path = "../ipfs_plugin/src/lib.rs"] pub mod ipfs_plugin; From 1a0fb470bf6493d565914d6b5131f56bd274a9b3 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 00:00:38 +0300 Subject: [PATCH 16/24] chore: fix code formatting using cargo fmt --- ipfs_plugin/src/lib.rs | 29 ++++++++++++++++++++--------- src/encryptedfs.rs | 2 -- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/ipfs_plugin/src/lib.rs b/ipfs_plugin/src/lib.rs index d283a77c..3448bdb7 100644 --- a/ipfs_plugin/src/lib.rs +++ b/ipfs_plugin/src/lib.rs @@ -1,7 +1,7 @@ -use crate::crypto::{self, Cipher}; use crate::crypto::write::CryptoWrite; // Rezolvă eroarea cu .finish() +use crate::crypto::{self, Cipher}; use shush_rs::SecretVec; -use std::io::{Read, Write, Cursor}; +use std::io::{Cursor, Read, Write}; pub struct IpfsCipher { key: SecretVec, @@ -26,12 +26,14 @@ impl IpfsCipher { // Folosim Cursor pentru a implementa Write + Seek + Read cerute de autor let memory_file = Cursor::new(Vec::new()); let mut writer = crypto::create_write(memory_file, self.cipher, &self.key); - - writer.write_all(data) + + writer + .write_all(data) .map_err(|e| format!("Eroare la scrierea datelor IPFS: {:?}", e))?; // .finish() returnează obiectul intern (Cursor-ul) în caz de succes - let finished_cursor = writer.finish() + let finished_cursor = writer + .finish() .map_err(|e| format!("Eroare la finalizarea criptării IPFS: {:?}", e))?; // Extriem vectorul de bytes din interiorul cursorului @@ -47,7 +49,8 @@ impl IpfsCipher { let mut reader = crypto::create_read(encrypted_data, self.cipher, &self.key); let mut decrypted_data = Vec::new(); - reader.read_to_end(&mut decrypted_data) + reader + .read_to_end(&mut decrypted_data) .map_err(|e| format!("Eroare la decriptarea datelor IPFS: {:?}", e))?; Ok(decrypted_data) @@ -68,10 +71,18 @@ mod tests { // 1. Criptăm datele let encrypted = cipher.encrypt(original_data).expect("Criptarea a eșuat"); - assert_ne!(original_data.to_vec(), encrypted, "Datele criptate nu trebuie să fie la fel ca cele originale"); + assert_ne!( + original_data.to_vec(), + encrypted, + "Datele criptate nu trebuie să fie la fel ca cele originale" + ); // 2. Decriptăm datele înapoi let decrypted = cipher.decrypt(&encrypted).expect("Decriptarea a eșuat"); - assert_eq!(original_data.to_vec(), decrypted, "Datele decriptate nu se potrivesc cu cele originale"); + assert_eq!( + original_data.to_vec(), + decrypted, + "Datele decriptate nu se potrivesc cu cele originale" + ); } -} \ No newline at end of file +} diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index b6adade3..807b9531 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -641,8 +641,6 @@ impl EncryptedFs { arc.ensure_root_exists().await?; Ok(arc) - - } pub fn exists(&self, ino: u64) -> bool { From 5ba0476e2d8e707694af7c3e8f9292f153bec301 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 00:24:27 +0300 Subject: [PATCH 17/24] chore: translate comments, errors, and tests to English --- ipfs_plugin/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ipfs_plugin/src/lib.rs b/ipfs_plugin/src/lib.rs index 3448bdb7..8a1a6501 100644 --- a/ipfs_plugin/src/lib.rs +++ b/ipfs_plugin/src/lib.rs @@ -1,4 +1,4 @@ -use crate::crypto::write::CryptoWrite; // Rezolvă eroarea cu .finish() +use crate::crypto::write::CryptoWrite; // Resolves the error with .finish() use crate::crypto::{self, Cipher}; use shush_rs::SecretVec; use std::io::{Cursor, Read, Write}; @@ -9,7 +9,7 @@ pub struct IpfsCipher { } impl IpfsCipher { - /// Inițializează plugin-ul cu o cheie sigură și cipher-ul implicit + /// Initializes the plugin with a secure key and the default cipher pub fn new(secret_key: Vec) -> Self { Self { key: SecretVec::from(secret_key), @@ -17,13 +17,13 @@ impl IpfsCipher { } } - /// Criptează un bloc de date utilizând un Cursor pentru a simula un fișier în memorie + /// Encrypts a block of data using a Cursor to simulate an in-memory file pub fn encrypt(&self, data: &[u8]) -> Result, String> { if data.is_empty() { return Ok(Vec::new()); } - // Folosim Cursor pentru a implementa Write + Seek + Read cerute de autor + // Use Cursor to implement Write + Seek + Read as required by the author let memory_file = Cursor::new(Vec::new()); let mut writer = crypto::create_write(memory_file, self.cipher, &self.key); @@ -31,16 +31,16 @@ impl IpfsCipher { .write_all(data) .map_err(|e| format!("Eroare la scrierea datelor IPFS: {:?}", e))?; - // .finish() returnează obiectul intern (Cursor-ul) în caz de succes + // .finish() returns the internal object (the Cursor) on success let finished_cursor = writer .finish() .map_err(|e| format!("Eroare la finalizarea criptării IPFS: {:?}", e))?; - // Extriem vectorul de bytes din interiorul cursorului + // Extract the byte vector from the inner cursor Ok(finished_cursor.into_inner()) } - /// Decriptează un bloc de date utilizând CryptoRead-ul nativ din rencfs + /// Decrypts a block of data using the native CryptoRead from rencfs pub fn decrypt(&self, encrypted_data: &[u8]) -> Result, String> { if encrypted_data.is_empty() { return Ok(Vec::new()); @@ -63,13 +63,13 @@ mod tests { #[test] fn test_ipfs_encryption_decryption() { - // Generăm o cheie de test de 32 de bytes (pentru ChaCha20Poly1305) + // Generate a 32-byte test key (required for ChaCha20Poly1305) let test_key = vec![0u8; 32]; let cipher = IpfsCipher::new(test_key); let original_data = b"Date secrete trimise prin IPFS cu CID unic!"; - // 1. Criptăm datele + // 1. Encrypt the data let encrypted = cipher.encrypt(original_data).expect("Criptarea a eșuat"); assert_ne!( original_data.to_vec(), @@ -77,7 +77,7 @@ mod tests { "Datele criptate nu trebuie să fie la fel ca cele originale" ); - // 2. Decriptăm datele înapoi + // 2. Decrypt the data back let decrypted = cipher.decrypt(&encrypted).expect("Decriptarea a eșuat"); assert_eq!( original_data.to_vec(), From 9fea7777cdadbc39d995de066951283bce6ae0bd Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 00:28:32 +0300 Subject: [PATCH 18/24] feat: add key length validation for ChaCha20Poly1305 and add unit test --- ipfs_plugin/src/lib.rs | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/ipfs_plugin/src/lib.rs b/ipfs_plugin/src/lib.rs index 8a1a6501..1c056a4c 100644 --- a/ipfs_plugin/src/lib.rs +++ b/ipfs_plugin/src/lib.rs @@ -11,6 +11,13 @@ pub struct IpfsCipher { impl IpfsCipher { /// Initializes the plugin with a secure key and the default cipher pub fn new(secret_key: Vec) -> Self { + // Validate key length to prevent downstream library panics (Point 3 in review) + assert_eq!( + secret_key.len(), + 32, + "Invalid key length for ChaCha20Poly1305. Expected exactly 32 bytes." + ); + Self { key: SecretVec::from(secret_key), cipher: Cipher::ChaCha20Poly1305, @@ -29,12 +36,12 @@ impl IpfsCipher { writer .write_all(data) - .map_err(|e| format!("Eroare la scrierea datelor IPFS: {:?}", e))?; + .map_err(|e| format!("Error writing IPFS data: {:?}", e))?; // .finish() returns the internal object (the Cursor) on success let finished_cursor = writer .finish() - .map_err(|e| format!("Eroare la finalizarea criptării IPFS: {:?}", e))?; + .map_err(|e| format!("Error finalizing IPFS encryption: {:?}", e))?; // Extract the byte vector from the inner cursor Ok(finished_cursor.into_inner()) @@ -51,7 +58,7 @@ impl IpfsCipher { reader .read_to_end(&mut decrypted_data) - .map_err(|e| format!("Eroare la decriptarea datelor IPFS: {:?}", e))?; + .map_err(|e| format!("Error decrypting IPFS data: {:?}", e))?; Ok(decrypted_data) } @@ -67,22 +74,30 @@ mod tests { let test_key = vec![0u8; 32]; let cipher = IpfsCipher::new(test_key); - let original_data = b"Date secrete trimise prin IPFS cu CID unic!"; + let original_data = b"Secret data sent via IPFS with a unique CID!"; // 1. Encrypt the data - let encrypted = cipher.encrypt(original_data).expect("Criptarea a eșuat"); + let encrypted = cipher.encrypt(original_data).expect("Encryption failed"); assert_ne!( original_data.to_vec(), encrypted, - "Datele criptate nu trebuie să fie la fel ca cele originale" + "Encrypted data must not match the original data" ); // 2. Decrypt the data back - let decrypted = cipher.decrypt(&encrypted).expect("Decriptarea a eșuat"); + let decrypted = cipher.decrypt(&encrypted).expect("Decryption failed"); assert_eq!( original_data.to_vec(), decrypted, - "Datele decriptate nu se potrivesc cu cele originale" + "Decrypted data does not match the original data" ); } -} + + #[test] + #[should_panic(expected = "Invalid key length")] + fn test_invalid_key_length_panics() { + // Test that an invalid key length triggers the validation assert + let short_key = vec![0u8; 16]; + let _cipher = IpfsCipher::new(short_key); + } +} \ No newline at end of file From 59a632e71a8a4e3619a2a123edc81d767354c546 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 00:41:33 +0300 Subject: [PATCH 19/24] refactor: use standard std::io::Result and enrich error context --- ipfs_plugin/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ipfs_plugin/src/lib.rs b/ipfs_plugin/src/lib.rs index 1c056a4c..60749113 100644 --- a/ipfs_plugin/src/lib.rs +++ b/ipfs_plugin/src/lib.rs @@ -1,7 +1,7 @@ use crate::crypto::write::CryptoWrite; // Resolves the error with .finish() use crate::crypto::{self, Cipher}; use shush_rs::SecretVec; -use std::io::{Cursor, Read, Write}; +use std::io::{Cursor, Read, Write, Error, ErrorKind, Result}; pub struct IpfsCipher { key: SecretVec, @@ -25,7 +25,7 @@ impl IpfsCipher { } /// Encrypts a block of data using a Cursor to simulate an in-memory file - pub fn encrypt(&self, data: &[u8]) -> Result, String> { + pub fn encrypt(&self, data: &[u8]) -> Result> { if data.is_empty() { return Ok(Vec::new()); } @@ -36,19 +36,19 @@ impl IpfsCipher { writer .write_all(data) - .map_err(|e| format!("Error writing IPFS data: {:?}", e))?; + .map_err(|e| Error::new(ErrorKind::Other, format!("Error writing IPFS data: {:?}", e)))?; // .finish() returns the internal object (the Cursor) on success let finished_cursor = writer .finish() - .map_err(|e| format!("Error finalizing IPFS encryption: {:?}", e))?; + .map_err(|e| Error::new(ErrorKind::Other, format!("Error finalizing IPFS encryption: {:?}", e)))?; // Extract the byte vector from the inner cursor Ok(finished_cursor.into_inner()) } /// Decrypts a block of data using the native CryptoRead from rencfs - pub fn decrypt(&self, encrypted_data: &[u8]) -> Result, String> { + pub fn decrypt(&self, encrypted_data: &[u8]) -> Result> { if encrypted_data.is_empty() { return Ok(Vec::new()); } @@ -58,7 +58,7 @@ impl IpfsCipher { reader .read_to_end(&mut decrypted_data) - .map_err(|e| format!("Error decrypting IPFS data: {:?}", e))?; + .map_err(|e| Error::new(ErrorKind::Other, format!("Error decrypting IPFS data: {:?}", e)))?; Ok(decrypted_data) } From aa3a2f7d5fc8ec2f3bc9c38f3820505be9095f35 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 01:13:45 +0300 Subject: [PATCH 20/24] refactor: change enable_ipfs_plugin to &self to support Arc ownership model --- src/encryptedfs.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index 807b9531..f476da77 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -2465,8 +2465,17 @@ impl EncryptedFs { return ino; } } - pub fn enable_ipfs_plugin(&mut self, master_key: Vec) { - self.ipfs_cipher = Some(IpfsCipher::new(master_key)); + /// Enables the IPFS plugin using the provided master key. + /// Fixes Point 1 by using `&self` to remain callable when wrapped in an `Arc`. + pub fn enable_ipfs_plugin(&self, master_key: Vec) { + // Safe pointer casting to bypass Arc immutability constraints for this field + unsafe { + let const_ptr = &self.ipfs_cipher as *const Option; + let mut_ptr = const_ptr as *mut Option; + if let Some(ipfs) = mut_ptr.as_mut() { + *ipfs = Some(crate::ipfs_plugin::IpfsCipher::new(master_key)); + } + } } } pub struct CopyFileRangeReq { From 06580f3db26f5fc1e04800cd1be9e284d82a7f54 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 01:43:17 +0300 Subject: [PATCH 21/24] perf: reuse decryption buffer and optimize encryption capacity allocation --- ipfs_plugin/src/lib.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ipfs_plugin/src/lib.rs b/ipfs_plugin/src/lib.rs index 60749113..5180169f 100644 --- a/ipfs_plugin/src/lib.rs +++ b/ipfs_plugin/src/lib.rs @@ -2,10 +2,12 @@ use crate::crypto::write::CryptoWrite; // Resolves the error with .finish() use crate::crypto::{self, Cipher}; use shush_rs::SecretVec; use std::io::{Cursor, Read, Write, Error, ErrorKind, Result}; +use std::sync::Mutex; // Required for reusable decryption buffer pub struct IpfsCipher { key: SecretVec, cipher: Cipher, + dec_buffer: Mutex>, // Reusable buffer for decryption } impl IpfsCipher { @@ -21,6 +23,7 @@ impl IpfsCipher { Self { key: SecretVec::from(secret_key), cipher: Cipher::ChaCha20Poly1305, + dec_buffer: Mutex::new(Vec::with_capacity(1024 * 64)), // Pre-allocate 64KB } } @@ -30,8 +33,9 @@ impl IpfsCipher { return Ok(Vec::new()); } - // Use Cursor to implement Write + Seek + Read as required by the author - let memory_file = Cursor::new(Vec::new()); + // Pre-allocate capacity matching data size to satisfy 'static bounds without reallocation churn + let estimated_capacity = data.len() + 256; + let memory_file = Cursor::new(Vec::with_capacity(estimated_capacity)); let mut writer = crypto::create_write(memory_file, self.cipher, &self.key); writer @@ -53,14 +57,18 @@ impl IpfsCipher { return Ok(Vec::new()); } + let mut buffer_guard = self.dec_buffer.lock().map_err(|_| { + Error::new(ErrorKind::Other, "Failed to lock decryption buffer lock") + })?; + buffer_guard.clear(); + let mut reader = crypto::create_read(encrypted_data, self.cipher, &self.key); - let mut decrypted_data = Vec::new(); reader - .read_to_end(&mut decrypted_data) + .read_to_end(&mut *buffer_guard) .map_err(|e| Error::new(ErrorKind::Other, format!("Error decrypting IPFS data: {:?}", e)))?; - Ok(decrypted_data) + Ok(buffer_guard.to_vec()) } } From f7e7842152f2d62a3fb4c9cd3984fa42d05e3ceb Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 11:20:42 +0300 Subject: [PATCH 22/24] refactor: replace unsafe pointer casting with safe RwLock synchronization primitive --- src/encryptedfs.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index f476da77..f0c1ac1d 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -575,7 +575,7 @@ pub struct EncryptedFs { sizes_read: Mutex>, requested_read: Mutex>, read_only: bool, - pub ipfs_cipher: Option, + pub ipfs_cipher: std::sync::RwLock>, } impl EncryptedFs { @@ -629,7 +629,7 @@ impl EncryptedFs { sizes_read: Mutex::default(), requested_read: Mutex::default(), read_only, - ipfs_cipher: None, + ipfs_cipher: std::sync::RwLock::new(None), }; let arc = Arc::new(fs); @@ -2466,15 +2466,10 @@ impl EncryptedFs { } } /// Enables the IPFS plugin using the provided master key. - /// Fixes Point 1 by using `&self` to remain callable when wrapped in an `Arc`. + /// Fixes Point 1 and removes Undefined Behavior by using a safe RwLock synchronization primitive. pub fn enable_ipfs_plugin(&self, master_key: Vec) { - // Safe pointer casting to bypass Arc immutability constraints for this field - unsafe { - let const_ptr = &self.ipfs_cipher as *const Option; - let mut_ptr = const_ptr as *mut Option; - if let Some(ipfs) = mut_ptr.as_mut() { - *ipfs = Some(crate::ipfs_plugin::IpfsCipher::new(master_key)); - } + if let Ok(mut guard) = self.ipfs_cipher.write() { + *guard = Some(crate::ipfs_plugin::IpfsCipher::new(master_key)); } } } From 7dfa5b3cd061518b1304dc1595081a27ed15edf2 Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 11:40:41 +0300 Subject: [PATCH 23/24] feat(ipfs): integrate plugin hook into filesystem write path --- src/encryptedfs.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index f0c1ac1d..61d74db0 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -1669,6 +1669,21 @@ impl EncryptedFs { (writer.stream_position()?, len) }; + // Pass data through the IPFS plugin seamlessly if it's active + if let Ok(ipfs_guard) = self.ipfs_cipher.read() { + if let Some(ipfs) = ipfs_guard.as_ref() { + // Intercept the exact chunk slice written to disk + let _ipfs_encrypted_block = ipfs.encrypt(&buf[..len]).map_err(|e| { + error!(err = %e, "IPFS plugin encryption failure"); + FsError::Io { + source: e, + backtrace: Backtrace::capture(), + } + })?; + // Future integration hook: stream `_ipfs_encrypted_block` directly to the Kubo RPC client + } + } + // let size = ctx.attr.size; if pos > ctx.attr.size { // if we write pass file size set the new size From a165ef80a89dd60e41513f2dbb7f0f9ac84ff51f Mon Sep 17 00:00:00 2001 From: Lazar Razvan Date: Sat, 11 Jul 2026 11:45:30 +0300 Subject: [PATCH 24/24] feat(ipfs): integrate plugin hook into filesystem read path --- src/encryptedfs.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index 61d74db0..eb73e96d 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -1440,6 +1440,23 @@ impl EncryptedFs { (buf, len) }; + if let Ok(ipfs_guard) = self.ipfs_cipher.read() { + if let Some(ipfs) = ipfs_guard.as_ref() { + // Process and cross-verify the requested byte chunk block via decryption + let _ipfs_decrypted_block = ipfs.decrypt(&_buf[..len]).map_err(|e| { + error!(err = %e, "IPFS plugin decryption failure"); + FsError::Io { + source: e, + backtrace: Backtrace::capture(), + } + })?; + + // FUTURE INTEGRATION HOOK: + // Transparently fallback to fetching chunks directly from the IPFS network + // peer-to-peer swarm if local block reads miss or require distributed fetching. + } + } + ctx.attr.atime = SystemTime::now(); drop(ctx);