148 lines
4.8 KiB
Rust
148 lines
4.8 KiB
Rust
|
|
//! Multi-backend encryption example.
|
||
|
|
//!
|
||
|
|
//! Demonstrates how to switch between different encryption backends
|
||
|
|
//! using the same unified API.
|
||
|
|
//!
|
||
|
|
//! # Key Point
|
||
|
|
//!
|
||
|
|
//! The same code path works with Age, SOPS, AWS KMS, GCP KMS, Azure KMS,
|
||
|
|
//! SecretumVault. Just change the backend specification - no code changes
|
||
|
|
//! needed!
|
||
|
|
//!
|
||
|
|
//! # Usage
|
||
|
|
//!
|
||
|
|
//! ```bash
|
||
|
|
//! # Test with Age backend
|
||
|
|
//! age-keygen -o ~/.age/key.txt
|
||
|
|
//! cargo run --example multi_backend --features age
|
||
|
|
//!
|
||
|
|
//! # Test with SOPS backend (requires .sops.yaml)
|
||
|
|
//! cargo run --example multi_backend --features sops
|
||
|
|
//!
|
||
|
|
//! # Test with both (shows feature-gating)
|
||
|
|
//! cargo run --example multi_backend --features age,sops
|
||
|
|
//! ```
|
||
|
|
|
||
|
|
use encrypt::{decrypt, encrypt, is_available, BackendSpec};
|
||
|
|
|
||
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||
|
|
println!("=== Multi-Backend Encryption Example ===\n");
|
||
|
|
|
||
|
|
let secret = "my-application-secret";
|
||
|
|
|
||
|
|
// Define specs for different backends
|
||
|
|
let backends = vec![
|
||
|
|
("Age (local)", BackendSpec::age_default()),
|
||
|
|
("SOPS (AWS KMS)", BackendSpec::sops()),
|
||
|
|
(
|
||
|
|
"SecretumVault (PQC)",
|
||
|
|
BackendSpec::secretumvault("https://vault.internal:8200", "hvs.token", "app-key"),
|
||
|
|
),
|
||
|
|
(
|
||
|
|
"AWS KMS",
|
||
|
|
BackendSpec::aws_kms("us-east-1", "arn:aws:kms:us-east-1:123456789:key/12345678"),
|
||
|
|
),
|
||
|
|
];
|
||
|
|
|
||
|
|
println!("Testing encryption with available backends:\n");
|
||
|
|
|
||
|
|
let mut success_count = 0;
|
||
|
|
let mut skipped_count = 0;
|
||
|
|
|
||
|
|
for (name, spec) in backends {
|
||
|
|
print!("{:<30} ", format!("{}...", name));
|
||
|
|
|
||
|
|
// Check if backend feature is enabled
|
||
|
|
if !is_available(&spec) {
|
||
|
|
println!("SKIPPED (feature not enabled)");
|
||
|
|
skipped_count += 1;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try encryption with this backend
|
||
|
|
match encrypt(secret, &spec) {
|
||
|
|
Ok(ciphertext) => {
|
||
|
|
// Try decryption
|
||
|
|
match decrypt(&ciphertext, &spec) {
|
||
|
|
Ok(plaintext) => {
|
||
|
|
if plaintext == secret {
|
||
|
|
println!("✓ SUCCESS");
|
||
|
|
success_count += 1;
|
||
|
|
} else {
|
||
|
|
println!("✗ FAILED (roundtrip mismatch)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Err(e) => {
|
||
|
|
println!("✗ FAILED (decrypt: {})", e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Err(e) => {
|
||
|
|
println!("✗ FAILED (encrypt: {})", e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
println!("\n=== Results ===");
|
||
|
|
println!("Successful: {}", success_count);
|
||
|
|
println!("Skipped (feature not enabled): {}", skipped_count);
|
||
|
|
|
||
|
|
// Show how to handle backend fallback
|
||
|
|
println!("\n=== Backend Fallback Pattern ===\n");
|
||
|
|
println!("Common pattern: Try production backend, fall back to local\n");
|
||
|
|
|
||
|
|
// Try SecretumVault (production)
|
||
|
|
let secretumvault_spec =
|
||
|
|
BackendSpec::secretumvault("https://vault.prod:8200", "token", "app-key");
|
||
|
|
|
||
|
|
if is_available(&secretumvault_spec) {
|
||
|
|
println!("Using SecretumVault (production, post-quantum ready)");
|
||
|
|
match encrypt(secret, &secretumvault_spec) {
|
||
|
|
Ok(_) => println!("✓ Encrypted with SecretumVault"),
|
||
|
|
Err(_) => println!("! SecretumVault unavailable, trying fallback..."),
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Fallback to Age
|
||
|
|
let age_spec = BackendSpec::age_default();
|
||
|
|
if is_available(&age_spec) {
|
||
|
|
println!("SecretumVault not available");
|
||
|
|
println!("Falling back to Age (local, X25519)");
|
||
|
|
match encrypt(secret, &age_spec) {
|
||
|
|
Ok(_) => println!("✓ Encrypted with Age"),
|
||
|
|
Err(e) => println!("✗ Age also failed: {}", e),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Show available backends
|
||
|
|
println!("\n=== Configuration Examples ===\n");
|
||
|
|
|
||
|
|
println!("Age (local X25519):");
|
||
|
|
println!(" BackendSpec::age_default()");
|
||
|
|
println!(" BackendSpec::age(\"/custom/path.txt\")\n");
|
||
|
|
|
||
|
|
println!("SOPS (multi-KMS via .sops.yaml):");
|
||
|
|
println!(" BackendSpec::sops()\n");
|
||
|
|
|
||
|
|
println!("SecretumVault (post-quantum ready):");
|
||
|
|
println!(" BackendSpec::secretumvault(\"https://vault:8200\", \"token\", \"key\")\n");
|
||
|
|
|
||
|
|
println!("AWS KMS:");
|
||
|
|
println!(" BackendSpec::aws_kms(\"us-east-1\", \"arn:aws:kms:...:key/...\")\n");
|
||
|
|
|
||
|
|
println!("GCP KMS:");
|
||
|
|
println!(" BackendSpec::gcp_kms(\"project\", \"global\", \"key\", \"global\")\n");
|
||
|
|
|
||
|
|
println!("Azure KMS:");
|
||
|
|
println!(" BackendSpec::azure_kms(\"vault-name\", \"tenant-id\")\n");
|
||
|
|
|
||
|
|
println!("Key Architecture Benefits:");
|
||
|
|
println!(" ✓ Same API for all backends");
|
||
|
|
println!(" ✓ Feature-gated compilation");
|
||
|
|
println!(" ✓ Easy to switch backends");
|
||
|
|
println!(" ✓ Fallback support");
|
||
|
|
println!(" ✓ No backend-specific code in application");
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|