fix(crypto): K-01 — format v3 canonical metadata authentication
This commit is contained in:
+54
-1
@@ -8,7 +8,7 @@ use zeroize::Zeroizing;
|
||||
use sanctum::crypto::{
|
||||
check_password_prefix_collision, dek_to_mnemonic, derive_kek, generate_dek, generate_salt,
|
||||
mnemonic_to_dek, set_allow_legacy_names, validate_password, wrap_slot0_payload,
|
||||
wrap_slot1_payload, KdfParams, FORMAT_VERSION,
|
||||
wrap_slot1_payload, KdfParams, FORMAT_VERSION, FORMAT_VERSION_V3,
|
||||
};
|
||||
use sanctum::mount::{format_drive, mount_container, unmount_drive, ContainerAuth};
|
||||
use sanctum::recovery::{
|
||||
@@ -280,6 +280,13 @@ enum Commands {
|
||||
#[arg(long, default_value_t = false)]
|
||||
insecure_url: bool,
|
||||
},
|
||||
|
||||
/// Migriert einen bestehenden Container auf Format V3 (Metadaten-Authentifizierung & Replay-Schutz)
|
||||
UpgradeFormat {
|
||||
/// Pfad zur .sanctum Containerdatei
|
||||
#[arg(short, long)]
|
||||
path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
fn parse_drive_letter(s: &str) -> Result<char> {
|
||||
@@ -623,6 +630,7 @@ fn handle_init(
|
||||
let db =
|
||||
Database::open(container_path).context("Konnte SQLite-Containerdatei nicht anlegen")?;
|
||||
|
||||
db.set_active_dek(dek.clone());
|
||||
db.init_schema_with_carrier(
|
||||
&salt,
|
||||
&kdf_params,
|
||||
@@ -1214,6 +1222,48 @@ fn handle_verify(container_path: &Path, full: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_upgrade_format(container_path: &Path) -> Result<()> {
|
||||
if !container_path.exists() {
|
||||
bail!(
|
||||
"Containerdatei '{}' existiert nicht.",
|
||||
container_path.display()
|
||||
);
|
||||
}
|
||||
|
||||
println!("┌─────────────────────────────────────────────────────────────┐");
|
||||
println!("│ Sanctum — Format V3 Upgrade │");
|
||||
println!("└─────────────────────────────────────────────────────────────┘");
|
||||
println!(" Container: {}", container_path.display());
|
||||
println!();
|
||||
|
||||
let password = rpassword::prompt_password("Master-Passwort: ")
|
||||
.context("Fehler beim Einlesen des Passworts")?;
|
||||
|
||||
let db = Database::open(container_path).context("Konnte Container-Datenbank nicht öffnen")?;
|
||||
let keys = match db.authenticate_password(&password)? {
|
||||
Some(k) => k,
|
||||
None => {
|
||||
bail!("Authentifizierung fehlgeschlagen: Falsches Passwort");
|
||||
}
|
||||
};
|
||||
|
||||
if keys.version() >= FORMAT_VERSION_V3 {
|
||||
println!(
|
||||
" • Container ist bereits Format V{} (keine Migration erforderlich).",
|
||||
keys.version()
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
db.upgrade_to_v3(keys.dek())?;
|
||||
db.checkpoint()?;
|
||||
|
||||
println!(" ✔ Container erfolgreich auf Format V3 aktualisiert!");
|
||||
println!(" • Metadaten-Authentifizierung (HMAC-SHA256) aktiviert.");
|
||||
println!(" • Replay-Schutz für Chunks (24-Byte AAD mit Generation) aktiviert.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_sync(
|
||||
container_path: &Path,
|
||||
source: &str,
|
||||
@@ -1520,6 +1570,9 @@ async fn run() -> Result<()> {
|
||||
Commands::Verify { path, full } => {
|
||||
handle_verify(&path, full)?;
|
||||
}
|
||||
Commands::UpgradeFormat { path } => {
|
||||
handle_upgrade_format(&path)?;
|
||||
}
|
||||
Commands::Sync {
|
||||
path,
|
||||
source,
|
||||
|
||||
Reference in New Issue
Block a user