Enhance CLI output: UTF-8 console codepage, VT colors, clean status cards
This commit is contained in:
+53
-33
@@ -2,12 +2,12 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
use tracing::info;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use sanctum::crypto::{derive_kek, generate_dek, generate_salt, wrap_dek, KdfParams};
|
||||
use sanctum::mount::{format_drive, mount_container, unmount_drive};
|
||||
use sanctum::storage::Database;
|
||||
use sanctum::ui;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "sanctum")]
|
||||
@@ -73,10 +73,11 @@ fn handle_init(container_path: &Path) -> Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
println!("============================================================");
|
||||
println!(" Sanctum Container Initialisierung");
|
||||
println!(" Zieldatei: {}", container_path.display());
|
||||
println!("============================================================");
|
||||
println!("┌─────────────────────────────────────────────────────────────┐");
|
||||
println!("│ Sanctum — Neuen verschlüsselten Container erstellen │");
|
||||
println!("└─────────────────────────────────────────────────────────────┘");
|
||||
println!(" Zieldatei: {}", container_path.display());
|
||||
println!();
|
||||
|
||||
let password = rpassword::prompt_password("Master-Passwort eingeben: ")
|
||||
.context("Fehler beim Einlesen des Passworts")?;
|
||||
@@ -92,20 +93,21 @@ fn handle_init(container_path: &Path) -> Result<()> {
|
||||
bail!("Die eingegebenen Passwörter stimmen nicht überein!");
|
||||
}
|
||||
|
||||
info!("Generiere KDF-Salt und leite KEK via Argon2id ab ...");
|
||||
println!();
|
||||
ui::step(1, 4, "🔑", "Leite KEK via Argon2id ab (M=64MB, T=3, P=4)...");
|
||||
let salt = generate_salt();
|
||||
let kdf_params = KdfParams::default();
|
||||
let kek = derive_kek(&password, &salt, &kdf_params)
|
||||
.context("KDF-Schlüsselableitung fehlgeschlagen")?;
|
||||
|
||||
info!("Erzeuge kryptografisch sicheren DEK via CSPRNG (OsRng) ...");
|
||||
ui::step(2, 4, "🎲", "Erzeuge kryptografisch sicheren DEK via CSPRNG...");
|
||||
let dek = generate_dek();
|
||||
|
||||
info!("Verschlüssele DEK mit KEK via AES-256-GCM ...");
|
||||
ui::step(3, 4, "🔒", "Verschlüssele DEK via AES-256-GCM...");
|
||||
let (wrapped_dek, header_nonce, header_tag) =
|
||||
wrap_dek(&kek, &dek).context("DEK-Wrapping fehlgeschlagen")?;
|
||||
|
||||
info!("Initialisiere SQLite-Containerstruktur mit WAL-Modus ...");
|
||||
ui::step(4, 4, "📦", "Initialisiere SQLite-Containerstruktur & WAL-Modus...");
|
||||
let db = Database::open(container_path)
|
||||
.context("Konnte SQLite-Containerdatei nicht anlegen")?;
|
||||
|
||||
@@ -116,31 +118,23 @@ fn handle_init(container_path: &Path) -> Result<()> {
|
||||
.context("Fehler beim finalen WAL-Checkpoint")?;
|
||||
|
||||
println!();
|
||||
println!("✔ Sanctum-Container erfolgreich initialisiert!");
|
||||
println!(" Container: {}", container_path.display());
|
||||
println!(" Format: Version 1 (Magic: SANCTUM\\0)");
|
||||
println!(" KDF: Argon2id (M=64MB, T=3, P=4)");
|
||||
println!(" Cipher: AES-256-GCM mit AEAD-Swap-Protection (1-MB Chunks)");
|
||||
println!("┌─────────────────────────────────────────────────────────────┐");
|
||||
println!("│ ✔ Sanctum-Container erfolgreich initialisiert! │");
|
||||
println!("└─────────────────────────────────────────────────────────────┘");
|
||||
println!();
|
||||
println!(" • Container: {}", container_path.display());
|
||||
println!(" • Format: Version 1 (Magic: SANCTUM\\0)");
|
||||
println!(" • KDF: Argon2id (M=64MB, T=3, P=4)");
|
||||
println!(" • Cipher: AES-256-GCM (1-MB Chunks, AEAD Swap-Schutz)");
|
||||
println!();
|
||||
println!(" Befehl zum Einbinden als Netzlaufwerk:");
|
||||
println!(" {}", ui::cyan(&format!("sanctum mount --path \"{}\" --drive S", container_path.display())));
|
||||
println!();
|
||||
println!("Zum Einbinden ausführen:");
|
||||
println!(
|
||||
" sanctum mount --path \"{}\" --drive S",
|
||||
container_path.display()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Tracing / Logging initialisieren (Standard-Filter: info)
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| EnvFilter::new("sanctum=info,dav_server=warn,hyper=warn")),
|
||||
)
|
||||
.init();
|
||||
|
||||
async fn run() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
@@ -149,20 +143,46 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
Commands::Mount { path, drive, port } => {
|
||||
let drive_char = parse_drive_letter(&drive)?;
|
||||
let password = rpassword::prompt_password(format!(
|
||||
let prompt_text = format!(
|
||||
"Master-Passwort für Container '{}' eingeben: ",
|
||||
path.display()
|
||||
))
|
||||
.context("Fehler beim Einlesen des Passworts")?;
|
||||
);
|
||||
let password = rpassword::prompt_password(prompt_text)
|
||||
.context("Fehler beim Einlesen des Passworts")?;
|
||||
|
||||
mount_container(&path, drive_char, port, &password).await?;
|
||||
}
|
||||
Commands::Unmount { drive } => {
|
||||
let drive_char = parse_drive_letter(&drive)?;
|
||||
let drive_str = format_drive(drive_char);
|
||||
print!(" {} Trenne Windows-Netzlaufwerk {} ... ", ui::dim("[-]"), drive_str);
|
||||
let _ = std::io::Write::flush(&mut std::io::stdout());
|
||||
unmount_drive(drive_char)?;
|
||||
println!("✔ Laufwerk {} erfolgreich getrennt.", format_drive(drive_char));
|
||||
println!("{}", ui::green("OK"));
|
||||
println!("{} Laufwerk {} erfolgreich getrennt.", ui::green("✔"), drive_str);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Windows Konsole für UTF-8 (Code Page 65001) und VT ANSI Processing konfigurieren
|
||||
ui::init_console();
|
||||
|
||||
// Tracing / Logging initialisieren (Standard-Filter: warn)
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| EnvFilter::new("sanctum=warn,dav_server=warn,hyper=warn")),
|
||||
)
|
||||
.init();
|
||||
|
||||
if let Err(err) = run().await {
|
||||
eprintln!();
|
||||
eprintln!("{} {:#}", ui::red("✖ Fehler:"), err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user