use rust_keyvault::{
backup::BackupConfig,
key::{SecretKey, VersionedKey},
storage::{FileStore, KeyStore, StorageConfig},
Algorithm, KeyId, KeyMetadata, KeyState,
};
use std::time::SystemTime;
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!(" Vault Backup & Restore Example\n");
println!("1. Creating vault with sample keys...");
let temp_dir = tempfile::tempdir()?;
let config = StorageConfig::default();
let mut vault = FileStore::new(temp_dir.path(), config)?;
let key_id1 = KeyId::from_bytes([1; 16]);
let secret_key1 = SecretKey::generate(Algorithm::ChaCha20Poly1305)?;
let metadata1 = KeyMetadata {
id: key_id1.clone(),
base_id: key_id1.clone(),
algorithm: Algorithm::ChaCha20Poly1305,
created_at: SystemTime::now(),
expires_at: None,
state: KeyState::Active,
version: 1,
};
vault.store(VersionedKey {
key: secret_key1,
metadata: metadata1,
})?;
println!(
" Added key 1: ChaCha20Poly1305 (ID: {})",
hex::encode(key_id1.as_bytes())
);
let key_id2 = KeyId::from_bytes([2; 16]);
let secret_key2 = SecretKey::generate(Algorithm::XChaCha20Poly1305)?;
let metadata2 = KeyMetadata {
id: key_id2.clone(),
base_id: key_id2.clone(),
algorithm: Algorithm::XChaCha20Poly1305,
created_at: SystemTime::now(),
expires_at: None,
state: KeyState::Active,
version: 1,
};
vault.store(VersionedKey {
key: secret_key2,
metadata: metadata2,
})?;
println!(
" Added key 2: XChaCha20Poly1305 (ID: {})",
hex::encode(key_id2.as_bytes())
);
let key_id3 = KeyId::from_bytes([3; 16]);
let secret_key3 = SecretKey::generate(Algorithm::Aes256Gcm)?;
let metadata3 = KeyMetadata {
id: key_id3.clone(),
base_id: key_id3.clone(),
algorithm: Algorithm::Aes256Gcm,
created_at: SystemTime::now(),
expires_at: None,
state: KeyState::Active,
version: 1,
};
vault.store(VersionedKey {
key: secret_key3,
metadata: metadata3,
})?;
println!(
" Added key 3: AES-256-GCM (ID: {})",
hex::encode(key_id3.as_bytes())
);
println!("\n2. Creating encrypted backup...");
let backup_password = b"super-secure-backup-password-2024!";
let backup_config = BackupConfig {
include_audit_logs: false,
compress: true,
encryption_password: backup_password.to_vec(),
comment: Some("Production backup - October 2025".to_string()),
};
let backup = vault.backup(backup_password, backup_config)?;
println!(" Backup created successfully");
println!(" - Format version: {}", backup.format_version);
println!(" - Keys backed up: {}", backup.metadata.key_count);
println!(" - Compressed: {}", backup.metadata.compressed);
println!(" - Data size: {} bytes", backup.metadata.data_size);
println!(" - Encryption: XChaCha20Poly1305 with Argon2id KDF");
println!(
" - Argon2 params: {} MiB memory, t={}, p={}",
backup.argon2_params.memory_kib / 1024,
backup.argon2_params.time_cost,
backup.argon2_params.parallelism
);
println!("\n3. Serializing backup to JSON...");
let backup_json = backup.to_json()?;
println!(" Backup serialized to {} bytes", backup_json.len());
println!(" (In production: save to vault_backup_2025_10_07.json)");
println!("\n4. Simulating disaster recovery scenario...");
println!(" - Original vault lost/corrupted");
println!(" - Creating new empty vault");
let temp_dir2 = tempfile::tempdir()?;
let config2 = StorageConfig::default();
let mut new_vault = FileStore::new(temp_dir2.path(), config2)?;
println!(" New vault created");
println!("\n5. Restoring from backup...");
let restored_count = new_vault.restore(&backup, backup_password)?;
println!(" Restored {} keys successfully", restored_count);
println!("\n6. Verifying data integrity...");
let restored_key1 = new_vault.retrieve(&key_id1)?;
assert_eq!(
restored_key1.metadata.algorithm,
Algorithm::ChaCha20Poly1305
);
println!(" Key 1 verified: ChaCha20Poly1305");
let restored_key2 = new_vault.retrieve(&key_id2)?;
assert_eq!(
restored_key2.metadata.algorithm,
Algorithm::XChaCha20Poly1305
);
println!(" Key 2 verified: XChaCha20Poly1305");
let restored_key3 = new_vault.retrieve(&key_id3)?;
assert_eq!(restored_key3.metadata.algorithm, Algorithm::Aes256Gcm);
println!(" Key 3 verified: AES-256-GCM");
println!("\n7. Testing wrong password protection...");
let wrong_password = b"wrong-password";
let temp_dir3 = tempfile::tempdir()?;
let config3 = StorageConfig::default();
let mut test_vault = FileStore::new(temp_dir3.path(), config3)?;
match test_vault.restore(&backup, wrong_password) {
Err(e) => {
println!(" Wrong password correctly rejected: {}", e);
}
Ok(_) => {
panic!("Should have failed with wrong password!");
}
}
println!("\n Backup & Restore Complete!");
println!("\nKey Features Demonstrated:");
println!(" • Full vault backup with all keys");
println!(" • Password-protected encryption (Argon2id + XChaCha20Poly1305)");
println!(" • Compression (reduces size by ~60-70%)");
println!(" • HMAC integrity verification");
println!(" • JSON serialization for portability");
println!(" • Complete data restoration");
println!(" • Wrong password detection");
println!("\nSecurity Guarantees:");
println!(" • 64 MiB memory cost (GPU-resistant)");
println!(" • Argon2id with t=4, p=4");
println!(" • XChaCha20Poly1305 AEAD encryption");
println!(" • HMAC-SHA256 integrity checks");
println!(" • Safe against replay attacks");
println!("\nUse Cases:");
println!(" • Disaster recovery");
println!(" • Vault migration");
println!(" • Scheduled backups");
println!(" • Compliance/archival");
println!(" • Multi-site replication");
Ok(())
}