From 70d03df676f50adc859cf0d96f15bd6667c7c36d Mon Sep 17 00:00:00 2001 From: harald Date: Wed, 9 Sep 2026 21:33:01 +0200 Subject: [PATCH] fix(security): implement P3 high-entropy carrier default and P5 manifest capacity guard --- src/carrier.rs | 16 +++++++++++++++- src/main.rs | 14 ++++++++++++-- tests/carrier_model_a_test.rs | 6 +++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/carrier.rs b/src/carrier.rs index d4e273d..d64b216 100644 --- a/src/carrier.rs +++ b/src/carrier.rs @@ -18,7 +18,7 @@ use futures_util::stream; use rand::rngs::OsRng; use rand::RngCore; use serde::{Deserialize, Serialize}; -use tracing::error; +use tracing::{error, warn}; use zeroize::{Zeroize, Zeroizing}; use crate::crypto::{decrypt_chunk, encrypt_chunk, CHUNK_SIZE}; @@ -268,6 +268,20 @@ pub struct CarrierFsInner { impl CarrierFsInner { pub fn save_manifest(&mut self) -> Result<()> { let manifest_bytes = serde_json::to_vec(&self.manifest)?; + if manifest_bytes.len() > (crate::crypto::CHUNK_SIZE - 64) { + bail!( + "Carrier-Manifest überschreitet die maximale Blockgröße ({} > {} Bytes).", + manifest_bytes.len(), + crate::crypto::CHUNK_SIZE - 64 + ); + } + if manifest_bytes.len() > 800_000 { + warn!( + "Carrier-Manifest erreicht 80% der Blockkapazität ({}/{} Bytes)", + manifest_bytes.len(), + crate::crypto::CHUNK_SIZE - 64 + ); + } write_carrier_block( &self.db, self.carrier_node_id, diff --git a/src/main.rs b/src/main.rs index 79334c3..febc0e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,8 +39,11 @@ enum Commands { #[arg(long, default_value_t = false)] with_hidden: bool, - /// Dateiname der Trägerdatei im Decoy-Vault (Standard: backup_image.iso) - #[arg(long, default_value = "backup_image.iso")] + /// Dateiname der Alibi-Trägerdatei im Decoy-Vault (Standard: system_backup.dat) + /// Tipp: Für maximale Plausible Deniability (CWE-209) empfehlen sich Dateitypen mit + /// natürlicherweise maximaler Entropie (.dat, .bin, .enc, .bak), um Anomalie-Detektion + /// in forensischen Entropie-Scannern zu verhindern. + #[arg(long, default_value = "system_backup.dat")] carrier_name: String, /// Größe der Trägerdatei (z. B. 100MB, 500MB, 1GB, 2GB; Standard: 1GB) @@ -245,6 +248,13 @@ fn handle_init( if with_hidden { println!(" Modus: Dual-Vault (Modell A: {})", ui::magenta("Alibi-Carrier")); println!(" Alibi: {} ({})", ui::cyan(carrier_name), ui::cyan(carrier_size_str)); + let lower = carrier_name.to_lowercase(); + if lower.ends_with(".iso") || lower.ends_with(".vhd") || lower.ends_with(".img") || lower.ends_with(".zip") { + println!( + " [{}] Hinweis zur Plausible Deniability: Dateitypen wie '.iso' oder '.zip' besitzen ein starres Format. Da Carrier-Blöcke verschlüsselt sind (Entropie ~8.0), empfehlen sich unformatierte Typen wie '.dat', '.bin' oder '.enc' für maximale forensische Unauffälligkeit.", + ui::yellow("Tipp") + ); + } } println!(); diff --git a/tests/carrier_model_a_test.rs b/tests/carrier_model_a_test.rs index 0027dde..9e7143e 100644 --- a/tests/carrier_model_a_test.rs +++ b/tests/carrier_model_a_test.rs @@ -25,7 +25,7 @@ fn temp_db_path(prefix: &str) -> PathBuf { async fn test_model_a_carrier_filesystem_and_accounting_attack_resistance() { let path = temp_db_path("carrier_accounting"); let carrier_size_bytes = 10 * 1024 * 1024; // 10 MB (10 Blöcke à 1 MB) - let carrier_name = "backup_image.iso"; + let carrier_name = "system_backup.dat"; let pass_decoy = "DecoyPassword2026!"; let pass_hidden = "SuperSecretHiddenPassword2026!"; @@ -89,7 +89,7 @@ async fn test_model_a_carrier_filesystem_and_accounting_attack_resistance() { assert_eq!(*auth_hidden.carrier_dek().unwrap(), *dek_0); assert_eq!(auth_hidden.carrier_node_id(), Some(carrier_node_id)); - // 2. Decoy Mount: Schutz der Alibi-Datei (backup_image.iso) + // 2. Decoy Mount: Schutz der Alibi-Datei (system_backup.dat) let decoy_fs = SanctumFs::with_carrier( db.clone(), auth_decoy.dek().clone(), @@ -100,7 +100,7 @@ async fn test_model_a_carrier_filesystem_and_accounting_attack_resistance() { 0, ); - let carrier_path = DavPath::new("/backup_image.iso").unwrap(); + let carrier_path = DavPath::new("/system_backup.dat").unwrap(); // Metadaten der Alibi-Datei im Decoy prüfen let carrier_meta = decoy_fs.metadata(&carrier_path).await.expect("Carrier meta");