use native_ossl::cipher::{AeadDecryptCtx, AeadEncryptCtx, CipherAlg};
use native_ossl::rand::Rand;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let alg = CipherAlg::fetch(c"AES-256-GCM", None)?;
println!("AES-256-GCM key length: {} bytes", alg.key_len());
println!("AES-256-GCM IV length: {} bytes", alg.iv_len());
let mut key = [0u8; 32];
let mut nonce = [0u8; 12];
Rand::fill(&mut key)?;
Rand::fill(&mut nonce)?;
let plaintext = b"secret message - keep it safe";
let aad = b"additional authenticated data";
let mut enc = AeadEncryptCtx::new(&alg, &key, &nonce, None)?;
enc.set_aad(aad)?;
let mut ciphertext = vec![0u8; plaintext.len()];
let n = enc.update(plaintext, &mut ciphertext)?;
enc.finalize(&mut ciphertext[n..])?;
let mut tag = [0u8; 16];
enc.tag(&mut tag)?;
println!(
"Ciphertext ({} bytes): {}",
ciphertext.len(),
hex::encode(&ciphertext)
);
println!("GCM tag: {}", hex::encode(tag));
let mut dec = AeadDecryptCtx::new(&alg, &key, &nonce, None)?;
dec.set_aad(aad)?;
dec.set_tag(&tag)?;
let mut recovered = vec![0u8; ciphertext.len()];
let n = dec.update(&ciphertext, &mut recovered)?;
dec.finalize(&mut recovered[n..])?;
assert_eq!(&recovered, plaintext);
println!("AES-256-GCM round-trip: OK");
let mut dec2 = AeadDecryptCtx::new(&alg, &key, &nonce, None)?;
dec2.set_aad(aad)?;
let mut bad_tag = tag;
bad_tag[0] ^= 0xff;
dec2.set_tag(&bad_tag)?;
let mut buf = vec![0u8; ciphertext.len()];
let _ = dec2.update(&ciphertext, &mut buf);
let auth_err = dec2.finalize(&mut buf[..0]);
assert!(auth_err.is_err(), "tampered tag must fail");
println!("Tampered tag rejected: OK");
Ok(())
}