//! AES-GCM authenticated encryption demonstration.
//!
//! ```sh
//! cargo run -p arcana --release --example aes_demo
//! ```

use arcana::BlockCipher;
use arcana::cipher::aes::Aes128;
use arcana::cipher::modes::Gcm;

fn hex(bytes: &[u8]) -> String {
    bytes.iter().map(|b| format!("{:02x}", b)).collect()
}

fn main() {
    // AES-128-GCM — NIST SP 800-38D
    let key = [0x42u8; 16];
    let nonce = [0x01u8; 12];
    let aad = b"associated data";
    let plaintext = b"hello, AES-GCM authenticated encryption!";

    let cipher = Aes128::new(&key);

    // Encrypt → (ciphertext, 16-byte tag)
    let (ct, tag) = Gcm::encrypt(&cipher, &nonce, aad, plaintext);
    println!("Plaintext:  {:?}", std::str::from_utf8(plaintext).unwrap());
    println!("Ciphertext: {}", hex(&ct));
    println!("Tag:        {}", hex(&tag));

    // Decrypt — returns None if the tag is invalid
    let pt = Gcm::decrypt(&cipher, &nonce, aad, &ct, &tag).expect("decryption should succeed with correct tag");
    assert_eq!(pt, plaintext);
    println!("Decrypted:  {:?}", std::str::from_utf8(&pt).unwrap());

    // Tamper test: flip one ciphertext byte → decryption must fail
    let mut ct_bad = ct.clone();
    ct_bad[0] ^= 0xFF;
    assert!(
        Gcm::decrypt(&cipher, &nonce, aad, &ct_bad, &tag).is_none(),
        "tampered ciphertext must be rejected"
    );
    println!("Tamper:     correctly rejected");

    println!("\nAll AES-GCM demos passed.");
}
