use crabgraph::{
aead::{AesGcm256, ChaCha20Poly1305},
key_rotation::KeyRotationManager,
CrabResult,
};
fn main() -> CrabResult<()> {
println!("🔐 CrabGraph Key Rotation Example\n");
println!("==========================================\n");
basic_rotation_demo()?;
re_encryption_demo()?;
key_lifecycle_demo()?;
multi_cipher_demo()?;
println!("\n✨ All key rotation examples completed successfully!");
Ok(())
}
fn basic_rotation_demo() -> CrabResult<()> {
println!("📋 Demo 1: Basic Key Rotation\n");
let mut manager = KeyRotationManager::<AesGcm256>::new()?;
println!(" ✓ Created KeyRotationManager");
println!(" Current version: {}\n", manager.current_version());
let user_data = b"User password: hunter2";
let (v1, ct1) = manager.encrypt(user_data, None)?;
println!(" ✓ Encrypted data with version {}", v1);
manager.rotate()?;
println!(" ✓ Rotated to version {}", manager.current_version());
let new_data = b"New user data";
let (v2, ct2) = manager.encrypt(new_data, None)?;
println!(" ✓ Encrypted new data with version {}\n", v2);
let decrypted_old = manager.decrypt(v1, &ct1, None)?;
println!(" ✓ Decrypted old data (v1): {:?}", String::from_utf8_lossy(&decrypted_old));
let decrypted_new = manager.decrypt(v2, &ct2, None)?;
println!(" ✓ Decrypted new data (v2): {:?}\n", String::from_utf8_lossy(&decrypted_new));
println!(" Available versions: {:?}\n", manager.available_versions());
Ok(())
}
fn re_encryption_demo() -> CrabResult<()> {
println!("🔄 Demo 2: Re-encryption Workflow\n");
let mut manager = KeyRotationManager::<AesGcm256>::new()?;
let records = [
b"Record 1: Alice's secret" as &[u8],
b"Record 2: Bob's secret",
b"Record 3: Carol's secret",
];
println!(" Encrypting {} records with version 1...", records.len());
let mut encrypted_records = Vec::new();
for (i, record) in records.iter().enumerate() {
let (version, ciphertext) = manager.encrypt(record, None)?;
encrypted_records.push((version, ciphertext));
println!(" ✓ Record {} encrypted (version {})", i + 1, version);
}
println!();
println!(" 🔑 Rotating to new key (version 2)...");
manager.rotate()?;
println!(" ✓ Rotation complete\n");
println!(" Re-encrypting {} records to version 2...", records.len());
let mut re_encrypted_records = Vec::new();
for (i, (old_version, old_ciphertext)) in encrypted_records.iter().enumerate() {
let (new_version, new_ciphertext) =
manager.re_encrypt(*old_version, old_ciphertext, None)?;
re_encrypted_records.push((new_version, new_ciphertext));
println!(" ✓ Record {} re-encrypted: v{} → v{}", i + 1, old_version, new_version);
}
println!();
println!(" Verifying re-encrypted records...");
for (i, (version, ciphertext)) in re_encrypted_records.iter().enumerate() {
let decrypted = manager.decrypt(*version, ciphertext, None)?;
assert_eq!(decrypted, records[i]);
println!(" ✓ Record {} verified", i + 1);
}
println!();
println!(" Removing old key (version 1)...");
manager.remove_version(1)?;
println!(" ✓ Old key removed");
println!(" Available versions: {:?}\n", manager.available_versions());
Ok(())
}
fn key_lifecycle_demo() -> CrabResult<()> {
println!("♻️ Demo 3: Key Lifecycle Management\n");
let mut manager = KeyRotationManager::<ChaCha20Poly1305>::with_max_versions(3)?;
println!(" Created manager with max 3 versions\n");
let data = b"Test data";
println!(" Performing rotations...");
let (v1, ct1) = manager.encrypt(data, None)?;
println!(" Version {}: {} total versions", v1, manager.version_count());
manager.rotate()?;
let (v2, ct2) = manager.encrypt(data, None)?;
println!(" Version {}: {} total versions", v2, manager.version_count());
manager.rotate()?;
let (v3, ct3) = manager.encrypt(data, None)?;
println!(" Version {}: {} total versions", v3, manager.version_count());
manager.rotate()?;
let (v4, _ct4) = manager.encrypt(data, None)?;
println!(" Version {}: {} total versions", v4, manager.version_count());
println!();
println!(" Version 1 available? {}", manager.has_version(1));
println!(" Version 2 available? {}", manager.has_version(2));
println!(" Version 3 available? {}", manager.has_version(3));
println!(" Version 4 available? {}", manager.has_version(4));
println!();
println!(" Attempting to decrypt old version 1 data...");
match manager.decrypt(v1, &ct1, None) {
Ok(_) => println!(" ✗ Unexpectedly succeeded"),
Err(_) => println!(" ✓ Correctly failed (key no longer available)"),
}
println!();
println!(" Decrypting version 2: {}", manager.decrypt(v2, &ct2, None).is_ok());
println!(" Decrypting version 3: {}", manager.decrypt(v3, &ct3, None).is_ok());
println!();
Ok(())
}
fn multi_cipher_demo() -> CrabResult<()> {
println!("🔀 Demo 4: Multiple Cipher Support\n");
let data = b"Test data for both ciphers";
println!(" Using AES-256-GCM:");
let aes_manager = KeyRotationManager::<AesGcm256>::new()?;
let (aes_v, aes_ct) = aes_manager.encrypt(data, None)?;
println!(" ✓ Encrypted with version {}", aes_v);
let aes_decrypted = aes_manager.decrypt(aes_v, &aes_ct, None)?;
println!(" ✓ Decrypted: {} bytes", aes_decrypted.len());
println!();
println!(" Using ChaCha20-Poly1305:");
let chacha_manager = KeyRotationManager::<ChaCha20Poly1305>::new()?;
let (chacha_v, chacha_ct) = chacha_manager.encrypt(data, None)?;
println!(" ✓ Encrypted with version {}", chacha_v);
let chacha_decrypted = chacha_manager.decrypt(chacha_v, &chacha_ct, None)?;
println!(" ✓ Decrypted: {} bytes", chacha_decrypted.len());
println!();
assert_eq!(aes_decrypted, chacha_decrypted);
println!(" ✓ Both ciphers produced identical plaintext\n");
Ok(())
}