use rust_keyvault::{
export::ExportedKey,
key::{SecretKey, VersionedKey},
storage::{FileStore, KeyStore, StorageConfig},
Algorithm, KeyId, KeyMetadata, KeyState,
};
use std::time::{Duration, SystemTime};
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("Key Export/Import Example\n");
println!("1. Creating source vault with a test key...");
let temp_dir = tempfile::tempdir()?;
let config = StorageConfig::default();
let mut source_vault = FileStore::new(temp_dir.path(), config)?;
let key_id = KeyId::from_bytes([1; 16]);
let secret_key = SecretKey::generate(Algorithm::ChaCha20Poly1305)?;
let metadata = KeyMetadata {
id: key_id.clone(),
base_id: key_id.clone(),
algorithm: Algorithm::ChaCha20Poly1305,
created_at: SystemTime::now(),
expires_at: Some(SystemTime::now() + Duration::from_secs(86400 * 365)), state: KeyState::Active,
version: 1,
};
let versioned_key = VersionedKey {
key: secret_key,
metadata,
};
source_vault.store(versioned_key)?;
println!(
" Key stored with ID: {}",
hex::encode(key_id.as_bytes())
);
println!("\n2. Exporting key with password protection...");
let export_password = b"super-secret-export-password-123!";
let exported_key = source_vault.export_key(&key_id, export_password)?;
println!(" Key exported successfully");
println!(
" - Export format version: {}",
exported_key.format_version
);
println!(
" - Wrapping algorithm: {:?}",
exported_key.wrapping_algorithm
);
println!(
" - Argon2 parameters: {} MiB memory, t={}, p={}",
exported_key.argon2_params.memory_kib / 1024,
exported_key.argon2_params.time_cost,
exported_key.argon2_params.parallelism
);
println!("\n3. Serializing to JSON for transmission/storage...");
let json_export = exported_key.to_json()?;
println!(" Serialized to {} bytes", json_export.len());
println!(
" First 100 chars: {}...",
&json_export[..100.min(json_export.len())]
);
println!("\n4. Deserializing from JSON...");
let deserialized = ExportedKey::from_json(&json_export)?;
println!(" Deserialized successfully");
println!(" - Algorithm: {:?}", deserialized.metadata.algorithm);
println!(" - Created at: {:?}", deserialized.metadata.created_at);
println!(" - Expires at: {:?}", deserialized.metadata.expires_at);
println!("\n5. Creating destination vault and importing key...");
let temp_dir2 = tempfile::tempdir()?;
let config2 = StorageConfig::default();
let mut dest_vault = FileStore::new(temp_dir2.path(), config2)?;
let imported_id = dest_vault.import_key(&deserialized, export_password)?;
println!(
" Key imported with ID: {}",
hex::encode(imported_id.as_bytes())
);
assert_eq!(imported_id, key_id, "Key IDs should match");
println!("\n6. Verifying imported key integrity...");
let original_key = source_vault.retrieve(&key_id)?;
let imported_key = dest_vault.retrieve(&imported_id)?;
assert_eq!(
original_key.key.expose_secret(),
imported_key.key.expose_secret(),
"Key material should be identical"
);
assert_eq!(
original_key.metadata.algorithm, imported_key.metadata.algorithm,
"Algorithm should match"
);
println!(" Key material verified - identical to original");
println!(" Metadata preserved correctly");
println!("\n7. Testing wrong password rejection...");
let wrong_password = b"wrong-password";
match dest_vault.import_key(&deserialized, wrong_password) {
Err(e) => {
println!(" Wrong password correctly rejected: {}", e);
}
Ok(_) => {
panic!("Should have failed with wrong password!");
}
}
println!("\nExport/Import workflow complete!");
println!("\nKey Features Demonstrated:");
println!(" • Password-protected key export using Argon2id");
println!(" • High-security parameters (64 MiB memory, t=4, p=4)");
println!(" • XChaCha20Poly1305 encryption for exported keys");
println!(" • JSON serialization for portability");
println!(" • Metadata preservation (algorithm, timestamps, expiry)");
println!(" • Audit trail logging");
println!(" • Wrong password detection");
println!("\nUse Cases:");
println!(" • Key distribution between vaults");
println!(" • Secure key backups");
println!(" • Key migration between systems");
println!(" • Multi-vault environments");
Ok(())
}