use zeroize::Zeroize; /// This library is created for AES/GCM stream encrypt or decrypt /// /// Structs for encryption: /// * Aes128GcmStreamEncryptor /// * Aes192GcmStreamEncryptor /// * Aes256GcmStreamEncryptor /// /// Structs for decryption: /// * Aes128GcmStreamDecryptor /// * Aes192GcmStreamDecryptor /// * Aes256GcmStreamDecryptor pub use decryptor::Aes128GcmStreamDecryptor; pub use decryptor::Aes192GcmStreamDecryptor; pub use decryptor::Aes256GcmStreamDecryptor; // ---------------------------------------- pub use encryptor::Aes128GcmStreamEncryptor; pub use encryptor::Aes192GcmStreamEncryptor; pub use encryptor::Aes256GcmStreamEncryptor; mod util; mod encryptor; mod decryptor; pub fn aes_gcm_encrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { match key.len() { 16 => aes_128_gcm_encrypt(key, nonce, message), 24 => aes_192_gcm_encrypt(key, nonce, message), 32 => aes_256_gcm_encrypt(key, nonce, message), _ => Err(format!("Bad key length")), } } pub fn aes_gcm_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { match key.len() { 16 => aes_128_gcm_decrypt(key, nonce, message), 24 => aes_192_gcm_decrypt(key, nonce, message), 32 => aes_256_gcm_decrypt(key, nonce, message), _ => Err(format!("Bad key length")), } } pub fn aes_128_gcm_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 16] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes128GcmStreamDecryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let final_block = gcm_stream.finalize()?; first_block.extend_from_slice(&final_block); key.zeroize(); Ok(first_block) } pub fn aes_192_gcm_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 24] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes192GcmStreamDecryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let final_block = gcm_stream.finalize()?; first_block.extend_from_slice(&final_block); key.zeroize(); Ok(first_block) } pub fn aes_256_gcm_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 32] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes256GcmStreamDecryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let final_block = gcm_stream.finalize()?; first_block.extend_from_slice(&final_block); key.zeroize(); Ok(first_block) } pub fn aes_128_gcm_encrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 16] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes128GcmStreamEncryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let (last_block, tag) = gcm_stream.finalize(); first_block.extend_from_slice(&last_block); first_block.extend_from_slice(&tag); key.zeroize(); Ok(first_block) } pub fn aes_192_gcm_encrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 24] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes192GcmStreamEncryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let (last_block, tag) = gcm_stream.finalize(); first_block.extend_from_slice(&last_block); first_block.extend_from_slice(&tag); key.zeroize(); Ok(first_block) } pub fn aes_256_gcm_encrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { let mut key: [u8; 32] = key.try_into().map_err(|_| format!("Bad key length"))?; let mut gcm_stream = Aes256GcmStreamEncryptor::new(key, nonce); let mut first_block = gcm_stream.update(message); let (last_block, tag) = gcm_stream.finalize(); first_block.extend_from_slice(&last_block); first_block.extend_from_slice(&tag); key.zeroize(); Ok(first_block) } #[test] fn test128() { use aes_gcm::{aead::{Aead, Nonce, Payload}, Aes128Gcm, KeyInit}; let knp = vec![ ([0; 16], [0; 12], &[] as &[u8], b"Hello World!" as &[u8]), ([0; 16], [0; 12], &[1; 16], b"Hello World!" as &[u8]), ([0; 16], [0; 12], &[1; 17], b"Hello World!" as &[u8]), ([0; 16], [0; 12], &[1; 32], b"Hello World!" as &[u8]), ([0; 16], [0; 12], &[1; 64], b"Hello World!" as &[u8]), ([0; 16], [0; 12], &[1, 2, 3], b"Hello World!" as &[u8]), ([1; 16], [0; 12], &[], b"Hello World!"), ([0; 16], [1; 12], &[], b"Hello World!"), ([1; 16], [1; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([1; 16], [1; 12], &[0; 129], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([0xff; 16], [0; 12], &[], b"Hello World!"), ([0; 16], [0xff; 12], &[], b"Hello World!"), ([0xff; 16], [0xff; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ([0xff; 16], [0xff; 12], &[11, 22, 33], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ]; for (key, nonce, aad, plaintext) in knp { // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes128GcmStreamEncryptor::new(key.clone(), &nonce); if !aad.is_empty() { encryptor.init_adata(aad); } ciphertext.extend_from_slice(&encryptor.update(plaintext)); let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); // decrypt 1 let mut decryptor = Aes128GcmStreamDecryptor::new(key.clone(), &nonce); if !aad.is_empty() { decryptor.init_adata(aad); } let mut plaintext1 = decryptor.update(ciphertext.as_slice()); let plaintext2 = decryptor.finalize().expect("decryptor decrypt"); plaintext1.extend_from_slice(&plaintext2); assert_eq!(plaintext, plaintext1.as_slice()); // decrypt 2 let cipher = Aes128Gcm::new_from_slice(&key).expect("new from key slice"); let mut decrypt_nonce = Nonce::::default(); let m: &mut [u8] = decrypt_nonce.as_mut(); for i in 0..m.len() { m[i] = nonce[i]; } let decrypted_plaintext = if aad.is_empty() { cipher.decrypt(&decrypt_nonce, ciphertext.as_slice()).expect("decrypt1") } else { cipher.decrypt(&decrypt_nonce, Payload { msg: ciphertext.as_slice(), aad, }).expect("decrypt2") }; assert_eq!(plaintext, decrypted_plaintext.as_slice()); } } #[test] fn test192() { let knp = vec![ ([0; 24], [0; 12], &[] as &[u8], b"Hello World!" as &[u8]), ([0; 24], [0; 12], &[1; 16], b"Hello World!" as &[u8]), ([0; 24], [0; 12], &[1; 17], b"Hello World!" as &[u8]), ([0; 24], [0; 12], &[1; 32], b"Hello World!" as &[u8]), ([0; 24], [0; 12], &[1; 64], b"Hello World!" as &[u8]), ([0; 24], [0; 12], &[1, 2, 3], b"Hello World!" as &[u8]), ([1; 24], [0; 12], &[], b"Hello World!"), ([0; 24], [1; 12], &[], b"Hello World!"), ([1; 24], [1; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([1; 24], [1; 12], &[0; 129], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([0xff; 24], [0; 12], &[], b"Hello World!"), ([0; 24], [0xff; 12], &[], b"Hello World!"), ([0xff; 24], [0xff; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ([0xff; 24], [0xff; 12], &[11, 22, 33], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ]; for (key, nonce, aad, plaintext) in knp { // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes192GcmStreamEncryptor::new(key.clone(), &nonce); if !aad.is_empty() { encryptor.init_adata(aad); } ciphertext.extend_from_slice(&encryptor.update(plaintext)); let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); // decrypt 1 let mut decryptor = Aes192GcmStreamDecryptor::new(key.clone(), &nonce); if !aad.is_empty() { decryptor.init_adata(aad); } let mut plaintext1 = decryptor.update(ciphertext.as_slice()); let plaintext2 = decryptor.finalize().expect("decryptor decrypt"); plaintext1.extend_from_slice(&plaintext2); assert_eq!(plaintext, plaintext1.as_slice()); // ops, aes_gcm not supports AES192 bit keys } } #[test] fn test256() { use aes_gcm::{aead::{Aead, Nonce, Payload}, Aes256Gcm, KeyInit}; let knp = vec![ ([0; 32], [0; 12], &[] as &[u8], b"Hello World!" as &[u8]), ([0; 32], [0; 12], &[1; 16], b"Hello World!" as &[u8]), ([0; 32], [0; 12], &[1; 17], b"Hello World!" as &[u8]), ([0; 32], [0; 12], &[1; 32], b"Hello World!" as &[u8]), ([0; 32], [0; 12], &[1; 64], b"Hello World!" as &[u8]), ([0; 32], [0; 12], &[1, 2, 3], b"Hello World!" as &[u8]), ([1; 32], [0; 12], &[], b"Hello World!"), ([0; 32], [1; 12], &[], b"Hello World!"), ([1; 32], [1; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([1; 32], [1; 12], &[0; 129], b"Hello World ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!"), ([0xff; 32], [0; 12], &[], b"Hello World!"), ([0; 32], [0xff; 12], &[], b"Hello World!"), ([0xff; 32], [0xff; 12], &[], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ([0xff; 32], [0xff; 12], &[11, 22, 33], b"Hello World ~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ ~~~~~~~~~!"), ]; for (key, nonce, aad, plaintext) in knp { println!("======= {} {} {} {}", hex::encode(key), hex::encode(nonce), hex::encode(aad), hex::encode(plaintext)); // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes256GcmStreamEncryptor::new(key.clone(), &nonce); if !aad.is_empty() { encryptor.init_adata(aad); } ciphertext.extend_from_slice(&encryptor.update(plaintext)); let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); // decrypt 1 let mut decryptor = Aes256GcmStreamDecryptor::new(key.clone(), &nonce); if !aad.is_empty() { decryptor.init_adata(aad); } let mut plaintext1 = decryptor.update(ciphertext.as_slice()); let plaintext2 = decryptor.finalize().expect("decryptor decrypt"); plaintext1.extend_from_slice(&plaintext2); assert_eq!(plaintext, plaintext1.as_slice()); // decrypt 2 let cipher = Aes256Gcm::new_from_slice(&key).expect("new from key slice"); let mut decrypt_nonce = Nonce::::default(); let m: &mut [u8] = decrypt_nonce.as_mut(); for i in 0..m.len() { m[i] = nonce[i]; } let decrypted_plaintext = if aad.is_empty() { cipher.decrypt(&decrypt_nonce, ciphertext.as_slice()).expect("decrypt1") } else { cipher.decrypt(&decrypt_nonce, Payload { msg: ciphertext.as_slice(), aad, }).expect("decrypt2") }; assert_eq!(plaintext, decrypted_plaintext.as_slice()); } } #[test] fn test256_stream() { use aes_gcm::{aead::{Aead, Nonce}, Aes256Gcm, KeyInit}; let key = [0u8; 32]; let nonce = [0; 12]; let mut plaintext = vec![]; // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes256GcmStreamEncryptor::new(key.clone(), &nonce); for i in 0..1025 { plaintext.extend_from_slice(&[(i % 128) as u8]); ciphertext.extend_from_slice(&encryptor.update(&[(i % 128) as u8])); } let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); // decrypt 1 let mut decryptor = Aes256GcmStreamDecryptor::new(key.clone(), &nonce); let mut plaintext1 = vec![]; for i in 0..ciphertext.len() { plaintext1.extend_from_slice(decryptor.update( &[ciphertext.as_slice()[i]]).as_slice()); } let plaintext2 = decryptor.finalize().expect("decryptor decrypt"); plaintext1.extend_from_slice(&plaintext2); assert_eq!(plaintext, plaintext1.as_slice()); // decrypt 2 let cipher = Aes256Gcm::new_from_slice(&key).expect("new from key slice"); let mut decrypt_nonce = Nonce::::default(); let m: &mut [u8] = decrypt_nonce.as_mut(); for i in 0..m.len() { m[i] = nonce[i]; } let decrypted_plaintext = cipher.decrypt(&decrypt_nonce, ciphertext.as_slice()).expect("decrypt1"); assert_eq!(plaintext, decrypted_plaintext.as_slice()); } #[test] fn test128_stream_and_array() { let key = [0u8; 16]; let nonce = [0; 12]; let mut plaintext = vec![]; // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes128GcmStreamEncryptor::new(key.clone(), &nonce); for i in 0..1025 { plaintext.extend_from_slice(&[(i % 128) as u8]); ciphertext.extend_from_slice(&encryptor.update(&[(i % 128) as u8])); } let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); let encrypted = aes_128_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_128_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); let encrypted = aes_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); } #[test] fn test192_stream_and_array() { let key = [0u8; 24]; let nonce = [0; 12]; let mut plaintext = vec![]; // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes192GcmStreamEncryptor::new(key.clone(), &nonce); for i in 0..1025 { plaintext.extend_from_slice(&[(i % 128) as u8]); ciphertext.extend_from_slice(&encryptor.update(&[(i % 128) as u8])); } let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); let encrypted = aes_192_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_192_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); let encrypted = aes_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); } #[test] fn test256_stream_and_array() { let key = [0u8; 32]; let nonce = [0; 12]; let mut plaintext = vec![]; // encrypt let mut ciphertext = vec![]; let mut encryptor = Aes256GcmStreamEncryptor::new(key.clone(), &nonce); for i in 0..1025 { plaintext.extend_from_slice(&[(i % 128) as u8]); ciphertext.extend_from_slice(&encryptor.update(&[(i % 128) as u8])); } let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); let encrypted = aes_256_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_256_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); let encrypted = aes_gcm_encrypt(&key, &nonce, &plaintext).unwrap(); let decrypted = aes_gcm_decrypt(&key, &nonce, &ciphertext).unwrap(); assert_eq!(ciphertext, encrypted); assert_eq!(plaintext, decrypted); } #[test] fn test125_ab_nonce() { let key = hex::decode("faf6a891866fac550ef548b4e5f6fbc98fccc6827cd943cc8d7539747f1d87bd").unwrap(); let key: [u8; 32] = key.try_into().map_err(|_| format!("Bad key length")).unwrap(); let nonce = hex::decode("cea500817694e16e734f07df422f6f52582d844e623746a96c5fbb4be2a38a6e").unwrap(); let ciphertext = hex::decode("c52dadf683c02e81d842f6563b").unwrap(); let tag = hex::decode("cc9062944525de37d3aa588c6a5676a2").unwrap(); let aad = b"firstName:"; let mut gcm_stream = Aes256GcmStreamDecryptor::new(key, &nonce); gcm_stream.init_adata(&aad[..]); let mut first_block = gcm_stream.update(&ciphertext); let second_block = gcm_stream.update(&tag); let final_block = gcm_stream.finalize().unwrap(); first_block.extend_from_slice(&second_block); first_block.extend_from_slice(&final_block); assert_eq!("John --- TEST", String::from_utf8(first_block).unwrap()); }