feat(anti-forensics): implement incremental auto-vacuum, chunk shredding, and plausible deniability

This commit is contained in:
2026-09-08 10:46:24 +02:00
parent 2cb065c8c0
commit 1e6854e9f5
8 changed files with 1386 additions and 270 deletions
+53 -15
View File
@@ -107,33 +107,56 @@ pub async fn mount_container(
.read_meta()
.context("Konnte Container-Header nicht lesen")?;
let (dek, version) = match auth {
let (dek, version, vault_id) = match auth {
ContainerAuth::Password(ref password) => {
ui::step(2, 4, "🔑", "Leite KEK via Argon2id ab...");
let kek = derive_kek(password, &meta.kdf_salt, &meta.kdf_params)
.context("Schlüsselableitung fehlgeschlagen")?;
let mut unwrapped = None;
ui::step(3, 4, "🔓", "Entschlüssele DEK via AES-256-GCM...");
let dek = unwrap_dek(
&kek,
&meta.wrapped_dek,
&meta.header_nonce,
&meta.header_tag,
)
.context("Ungültiges Master-Passwort oder Container beschädigt")?;
(dek, meta.version)
for slot in &meta.slots {
if let Ok(kek) = derive_kek(password, &slot.kdf_salt, &slot.kdf_params) {
if let Ok(dek) = unwrap_dek(
&kek,
&slot.wrapped_dek,
&slot.header_nonce,
&slot.header_tag,
) {
unwrapped = Some((dek, slot.version, slot.slot_id));
break;
}
}
}
match unwrapped {
Some((dek, ver, slot_id)) => {
ui::step(3, 4, "🔓", "Master-Passwort erfolgreich verifiziert & DEK entschlüsselt!");
(dek, ver, slot_id)
}
None => {
bail!("Ungültiges Master-Passwort oder Container beschädigt");
}
}
}
ContainerAuth::RecoveryKey(ref phrase) => {
ui::step(2, 4, "🔑", "Dekodiere DEK aus 24-Wort Notfallschlüssel...");
let dek = mnemonic_to_dek(phrase)
.context("Ungültiger 24-Wort Notfallschlüssel")?;
ui::step(3, 4, "🔓", "Notfallschlüssel erfolgreich verifiziert!");
(dek, meta.version)
let vault_id = if db.has_hidden_vault().unwrap_or(false) {
let is_hidden = {
let children = db.list_children_in_vault(2, 1, &dek).unwrap_or_default();
!children.is_empty()
};
if is_hidden { 1 } else { 0 }
} else {
0
};
(dek, meta.version, vault_id)
}
};
// WebDAV Filesystem und Handler konfigurieren (mit Anti-Leak Shield)
let fs = SanctumFs::with_options(db.clone(), dek, version, anti_leak);
// WebDAV Filesystem und Handler konfigurieren (mit Anti-Leak Shield & Vault-Routing)
let fs = SanctumFs::with_vault(db.clone(), dek, version, anti_leak, vault_id);
let last_activity = fs.last_activity();
let dav_server = DavHandler::builder()
.filesystem(Box::new(fs))
@@ -300,6 +323,9 @@ pub async fn mount_container(
println!(" • Container: {}", container_path.display());
println!(" • Netzlaufwerk: {} (im Windows Explorer bereit)", ui::cyan(&drive_str));
println!(" • WebDAV-URL: http://127.0.0.1:{}/", bound_port);
if vault_id == 1 {
println!(" • Vault: {} (Verschlüsselte Dateinamen)", ui::magenta("Hidden Vault (Slot 1)"));
}
if let Some(secs) = idle_timeout {
println!(" • Auto-Lock: Inaktivität nach {}s", secs);
}
@@ -350,6 +376,18 @@ pub async fn mount_container(
let _ = shutdown_tx.send(true);
let _ = server_handle.await;
// Storage-Kompaktierung (Incremental Vacuum), falls freie Seiten existieren
if let Ok(freelist) = db.freelist_count() {
if freelist > 0 {
print!(" {} Führe Storage-Kompaktierung aus ({} freie Seiten) ... ", ui::dim("[-]"), freelist);
let _ = std::io::Write::flush(&mut std::io::stdout());
match db.incremental_vacuum(None) {
Ok(freed) => println!("{} ({} Seiten freigegeben)", ui::green("OK"), freed),
Err(e) => println!("{}", ui::yellow(&format!("Warnung ({e})"))),
}
}
}
// SQLite WAL Checkpoint erzwingen
print!(" {} Führe SQLite WAL-Checkpoint aus ... ", ui::dim("[-]"));
let _ = std::io::Write::flush(&mut std::io::stdout());