use crate::aes_gcm::{GcmBlockMulFn, iv2pre_counter_block, increment_32_least_bits, gctr, define_block_s, xor_full_blocks};
use crate::aes::BLOCK_SIZE;
use futures::{AsyncWrite, io::{self, AsyncRead, AsyncReadExt, AsyncWriteExt}};
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum AesGcmAsyncError {
InvalidKeySize(usize),
InvalidIvSize(usize),
IoError(String),
AuthenticationFailed,
CryptoError(String),
}
impl fmt::Display for AesGcmAsyncError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AesGcmAsyncError::InvalidKeySize(size) => {
write!(f, "Invalid key size: {} bytes. Must be 16, 24, or 32 bytes", size)
}
AesGcmAsyncError::InvalidIvSize(size) => {
write!(f, "Invalid IV size: {} bytes. Must be at least 1 byte (longer IVs are hashed to 12 bytes)", size)
}
AesGcmAsyncError::IoError(msg) => {
write!(f, "I/O error: {}", msg)
}
AesGcmAsyncError::AuthenticationFailed => {
write!(f, "Authentication failed - message may be corrupted or tampered with")
}
AesGcmAsyncError::CryptoError(msg) => {
write!(f, "Cryptographic error: {}", msg)
}
}
}
}
impl std::error::Error for AesGcmAsyncError {}
impl From<io::Error> for AesGcmAsyncError {
fn from(err: io::Error) -> Self {
AesGcmAsyncError::IoError(err.to_string())
}
}
#[inline]
fn validate_key_size(key: &[u8]) -> Result<(), AesGcmAsyncError> {
match key.len() {
16 | 24 | 32 => Ok(()),
size => Err(AesGcmAsyncError::InvalidKeySize(size)),
}
}
#[inline]
fn validate_iv_size(iv: &[u8]) -> Result<(), AesGcmAsyncError> {
if iv.is_empty() {
Err(AesGcmAsyncError::InvalidIvSize(iv.len()))
} else {
Ok(())
}
}
const OPTIMAL_BUFFER_SIZE: usize = 64 * 1024;
pub async fn gcm_aes_encrypt_async<R, W>(
key: &[u8],
iv: &[u8],
mut reader: R,
mut writer: W,
aad: &[u8],
mul_fn: &GcmBlockMulFn,
) -> Result<[u8; 16], AesGcmAsyncError>
where
R: AsyncRead + Unpin,
W: AsyncWrite + Unpin,
{
validate_key_size(key)?;
validate_iv_size(iv)?;
let mut counter_block = iv2pre_counter_block(&iv, mul_fn);
let encrypted_block = crate::aes::encrypt(&counter_block, key);
increment_32_least_bits(&mut counter_block);
let mut buffer = vec![0u8; OPTIMAL_BUFFER_SIZE];
let mut cipher_text = Vec::new();
loop {
let n = reader.read(&mut buffer).await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to read data: {}", e)))?;
if n == 0 { break; }
let mut chunk_counter = counter_block.clone();
let cipher_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
writer.write_all(&cipher_chunk).await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
cipher_text.extend_from_slice(&cipher_chunk);
for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
increment_32_least_bits(&mut counter_block);
}
}
let s = define_block_s(&cipher_text, aad, mul_fn);
let tag = xor_full_blocks(&s, &encrypted_block);
writer.flush().await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to flush writer: {}", e)))?;
Ok(tag)
}
pub async fn gcm_aes_decrypt_async<R, W>(
key: &[u8],
iv: &[u8],
mut reader: R,
mut writer: W,
aad: &[u8],
mul_fn: &GcmBlockMulFn,
) -> Result<[u8; 16], AesGcmAsyncError>
where
R: AsyncRead + Unpin,
W: AsyncWrite + Unpin,
{
validate_key_size(key)?;
validate_iv_size(iv)?;
let mut counter_block = iv2pre_counter_block(&iv, mul_fn);
let encrypted_block = crate::aes::encrypt(&counter_block, key);
increment_32_least_bits(&mut counter_block);
let mut buffer = vec![0u8; OPTIMAL_BUFFER_SIZE];
let mut cipher_text = Vec::new();
loop {
let n = reader.read(&mut buffer).await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to read data: {}", e)))?;
if n == 0 { break; }
cipher_text.extend_from_slice(&buffer[..n]);
let mut chunk_counter = counter_block.clone();
let plain_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
writer.write_all(&plain_chunk).await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
increment_32_least_bits(&mut counter_block);
}
}
let s = define_block_s(&cipher_text, aad, mul_fn);
let tag = xor_full_blocks(&s, &encrypted_block);
writer.flush().await
.map_err(|e| AesGcmAsyncError::IoError(format!("Failed to flush writer: {}", e)))?;
Ok(tag)
}
#[cfg(test)]
mod tests {
use crate::aes_gcm::GcmBlockMulEnhancement;
use crate::aes_gcm::{
calculate_table_m, calculate_4bit_table_m, block_mul, block_mul_with_tables,
block_mul_with_4bit_tables, block_mul_with_m0_r, TABLE_R
};
use crate::aes;
use futures::io::Cursor;
use futures::executor::block_on;
use super::*;
#[test]
fn test_gcm_aes_128_encrypt() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let p = "".as_bytes();
let aad = "".as_bytes();
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(&cipher_text, &[]);
assert_eq!(
&tag,
&[
0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7,
0x45, 0x5a
]
);
let p = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let aad = "".as_bytes();
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2,
0xfe, 0x78
]
);
assert_eq!(
&tag,
&[
0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57,
0xbd, 0xdf
]
);
let cipher_key = [
0xAD, 0x7A, 0x2B, 0xD0, 0x3E, 0xAC, 0x83, 0x5A, 0x6F, 0x62, 0x0F, 0xDC, 0xB5, 0x06,
0xB3, 0x45,
];
let iv = [
0x12, 0x15, 0x35, 0x24, 0xC0, 0x89, 0x5E, 0x81, 0xB2, 0xC2, 0x84, 0x65,
];
let p = [
0x08, 0x00, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3A, 0x00, 0x02,
];
let aad = [
0xD6, 0x09, 0xB1, 0xF0, 0x56, 0x63, 0x7A, 0x0D, 0x46, 0xDF, 0x99, 0x8D, 0x88, 0xE5,
0x2E, 0x00, 0xB2, 0xC2, 0x84, 0x65, 0x12, 0x15, 0x35, 0x24, 0xC0, 0x89, 0x5E, 0x81,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x70, 0x1A, 0xFA, 0x1C, 0xC0, 0x39, 0xC0, 0xD7, 0x65, 0x12, 0x8A, 0x66, 0x5D, 0xAB,
0x69, 0x24, 0x38, 0x99, 0xBF, 0x73, 0x18, 0xCC, 0xDC, 0x81, 0xC9, 0x93, 0x1D, 0xA1,
0x7F, 0xBE, 0x8E, 0xDD, 0x7D, 0x17, 0xCB, 0x8B, 0x4C, 0x26, 0xFC, 0x81, 0xE3, 0x28,
0x4F, 0x2B, 0x7F, 0xBA, 0x71, 0x3D
]
);
assert_eq!(
&tag,
&[
0x4F, 0x8D, 0x55, 0xE7, 0xD3, 0xF0, 0x6F, 0xD5, 0xA1, 0x3C, 0x0C, 0x29, 0xB9, 0xD5,
0xB8, 0x80
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
]
);
assert_eq!(
&tag,
&[
0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
0xfa, 0xb4
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91
]
);
assert_eq!(
&tag,
&[
0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12,
0x1a, 0x47
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a,
0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9,
0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09,
0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
0xc2, 0x3f, 0x45, 0x98
]
);
assert_eq!(
&tag,
&[
0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2,
0xfc, 0xcb
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f,
0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c,
0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc,
0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
0x4c, 0x34, 0xae, 0xe5
]
);
assert_eq!(
&tag,
&[
0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99,
0xd0, 0x50
]
);
}
#[test]
fn test_gcm_aes_192_encrypt() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let p = [];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(&cipher_text, &[]);
assert_eq!(
&tag,
&[
0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57,
0x24, 0x35
]
);
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let p = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0,
0xf6, 0x00
]
);
assert_eq!(
&tag,
&[
0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
0xf0, 0xfb
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56
]
);
assert_eq!(
&tag,
&[
0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67,
0x4a, 0x14
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
0xcc, 0xda, 0x27, 0x10
]
);
assert_eq!(
&tag,
&[
0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27,
0x61, 0x8c
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32,
0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f,
0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65,
0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
0xa0, 0xf0, 0x62, 0xf7
]
);
assert_eq!(
&tag,
&[
0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35,
0x33, 0xf8
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
];
let iv = [
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc,
0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98,
0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0,
0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
0xe9, 0xb7, 0x37, 0x3b
]
);
assert_eq!(
&tag,
&[
0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76,
0xa6, 0xd9
]
);
}
#[test]
fn test_gcm_aes_256_encrypt() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let p = [];
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(&cipher_text, &[]);
assert_eq!(
&tag,
&[
0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb,
0x73, 0x8b
]
);
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let p = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3,
0x9d, 0x18
]
);
assert_eq!(
&tag,
&[
0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a,
0xb9, 0x19
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad
]
);
assert_eq!(
&tag,
&[
0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3,
0xcc, 0x6c
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62
]
);
assert_eq!(
&tag,
&[
0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d,
0x55, 0x1b
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98,
0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7,
0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c,
0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
0xf4, 0x7c, 0x9b, 0x1f
]
);
assert_eq!(
&tag,
&[
0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e,
0xa8, 0xf2
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e,
0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f,
0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3,
0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
0x44, 0xae, 0x7e, 0x3f
]
);
assert_eq!(
&tag,
&[
0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9,
0xf1, 0x9a
]
);
}
#[test]
fn test_calculate_m() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
let h = u128::from_be_bytes(h_block);
let m0 = calculate_table_m(h, 0);
assert_eq!(
block_mul(h, 254u128.reverse_bits()),
m0[254u8.reverse_bits() as usize]
);
assert_eq!(
block_mul(h, 1u128.reverse_bits()),
m0[1u8.reverse_bits() as usize]
);
assert_eq!(
block_mul(h, 0u128.reverse_bits()),
m0[0u8.reverse_bits() as usize]
);
assert_eq!(
block_mul(h, 2u128.reverse_bits()),
m0[2u8.reverse_bits() as usize]
);
assert_eq!(
block_mul(h, 4u128.reverse_bits()),
m0[4u8.reverse_bits() as usize]
);
assert_eq!(
block_mul(h, 37u128.reverse_bits()),
m0[37u8.reverse_bits() as usize]
);
let m1 = calculate_table_m(h, 1);
assert_eq!(block_mul(m0[254], 1u128.reverse_bits() >> 8), m1[254]);
assert_eq!(block_mul(m0[1], 1u128.reverse_bits() >> 8), m1[1]);
assert_eq!(block_mul(m0[4], 1u128.reverse_bits() >> 8), m1[4]);
assert_eq!(block_mul(m0[0], 1u128.reverse_bits() >> 8), m1[0]);
assert_eq!(block_mul(m0[2], 1u128.reverse_bits() >> 8), m1[2]);
assert_eq!(block_mul(m0[37], 1u128.reverse_bits() >> 8), m1[37]);
let m2 = calculate_table_m(h, 2);
assert_eq!(block_mul(m1[254], 1u128.reverse_bits() >> 8), m2[254]);
assert_eq!(block_mul(m1[1], 1u128.reverse_bits() >> 8), m2[1]);
assert_eq!(block_mul(m1[4], 1u128.reverse_bits() >> 8), m2[4]);
assert_eq!(block_mul(m1[0], 1u128.reverse_bits() >> 8), m2[0]);
assert_eq!(block_mul(m1[2], 1u128.reverse_bits() >> 8), m2[2]);
assert_eq!(block_mul(m1[37], 1u128.reverse_bits() >> 8), m2[37]);
assert_eq!(block_mul(m0[37], 1u128.reverse_bits() >> 16), m2[37]);
let m3 = calculate_table_m(h, 3);
assert_eq!(block_mul(m2[255], 1u128.reverse_bits() >> 8), m3[255]);
assert_eq!(block_mul(m2[11], 1u128.reverse_bits() >> 8), m3[11]);
assert_eq!(block_mul(m2[8], 1u128.reverse_bits() >> 8), m3[8]);
assert_eq!(block_mul(m2[15], 1u128.reverse_bits() >> 8), m3[15]);
assert_eq!(block_mul(m2[3], 1u128.reverse_bits() >> 8), m3[3]);
assert_eq!(block_mul(m2[33], 1u128.reverse_bits() >> 8), m3[33]);
assert_eq!(block_mul(m0[77], 1u128.reverse_bits() >> 24), m3[77]);
let m4 = calculate_table_m(h, 4);
assert_eq!(block_mul(m3[64], 1u128.reverse_bits() >> 8), m4[64]);
assert_eq!(block_mul(m3[32], 1u128.reverse_bits() >> 8), m4[32]);
assert_eq!(block_mul(m3[192], 1u128.reverse_bits() >> 8), m4[192]);
assert_eq!(block_mul(m3[12], 1u128.reverse_bits() >> 8), m4[12]);
assert_eq!(block_mul(m3[128], 1u128.reverse_bits() >> 8), m4[128]);
assert_eq!(block_mul(m3[129], 1u128.reverse_bits() >> 8), m4[129]);
assert_eq!(block_mul(m0[211], 1u128.reverse_bits() >> 32), m4[211]);
let m5 = calculate_table_m(h, 5);
assert_eq!(block_mul(m0[12], 1u128.reverse_bits() >> 40), m5[12]);
assert_eq!(block_mul(m1[15], 1u128.reverse_bits() >> 32), m5[15]);
assert_eq!(block_mul(m2[16], 1u128.reverse_bits() >> 24), m5[16]);
assert_eq!(block_mul(m3[128], 1u128.reverse_bits() >> 16), m5[128]);
let m6 = calculate_table_m(h, 6);
let m7 = calculate_table_m(h, 7);
let m8 = calculate_table_m(h, 8);
let m9 = calculate_table_m(h, 9);
let m10 = calculate_table_m(h, 10);
let m11 = calculate_table_m(h, 11);
let m12 = calculate_table_m(h, 12);
let m13 = calculate_table_m(h, 13);
let m14 = calculate_table_m(h, 14);
let m15 = calculate_table_m(h, 15);
assert_eq!(block_mul(m0[2], 1u128.reverse_bits() >> 120), m15[2]);
assert_eq!(block_mul(m1[3], 1u128.reverse_bits() >> 112), m15[3]);
assert_eq!(block_mul(m2[4], 1u128.reverse_bits() >> 104), m15[4]);
assert_eq!(block_mul(m3[5], 1u128.reverse_bits() >> 96), m15[5]);
assert_eq!(block_mul(m4[6], 1u128.reverse_bits() >> 88), m15[6]);
assert_eq!(block_mul(m5[7], 1u128.reverse_bits() >> 80), m15[7]);
assert_eq!(block_mul(m6[8], 1u128.reverse_bits() >> 72), m15[8]);
assert_eq!(block_mul(m7[9], 1u128.reverse_bits() >> 64), m15[9]);
assert_eq!(block_mul(m8[1], 1u128.reverse_bits() >> 56), m15[1]);
assert_eq!(block_mul(m9[255], 1u128.reverse_bits() >> 48), m15[255]);
assert_eq!(block_mul(m10[232], 1u128.reverse_bits() >> 40), m15[232]);
assert_eq!(block_mul(m11[192], 1u128.reverse_bits() >> 32), m15[192]);
assert_eq!(block_mul(m12[64], 1u128.reverse_bits() >> 24), m15[64]);
assert_eq!(block_mul(m13[17], 1u128.reverse_bits() >> 16), m15[17]);
assert_eq!(block_mul(m14[93], 1u128.reverse_bits() >> 8), m15[93]);
}
#[test]
fn test_gcm_aes_block_mul_with_tables() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
let h = u128::from_be_bytes(h_block);
let mut m = [[0u128; 256]; BLOCK_SIZE];
for i in 0..BLOCK_SIZE {
m[i] = calculate_table_m(h, i);
}
let x_block = [
0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
0xf0, 0xfb,
];
let x = u128::from_be_bytes(x_block);
let r1 = block_mul_with_tables(&m, x);
let r2 = block_mul(x, h);
assert_eq!(r1, r2);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::MTables.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
]
);
assert_eq!(
&tag,
&[
0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
0xfa, 0xb4
]
);
}
#[test]
fn test_gcm_aes_block_mul_with_4bit_tables() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
let h = u128::from_be_bytes(h_block);
let mut m = [[0u128; 16]; BLOCK_SIZE << 1];
for i in 0..m.len() {
m[i] = calculate_4bit_table_m(h, i);
}
let x_block = [
0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
0xf0, 0xfb,
];
let x = u128::from_be_bytes(x_block);
let r1 = block_mul_with_4bit_tables(&m, x);
let r2 = block_mul(x, h);
assert_eq!(r1, r2);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::M4BitTables.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
]
);
assert_eq!(
&tag,
&[
0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
0xfa, 0xb4
]
);
}
#[test]
fn test_gcm_aes_calculate_r_table() {
assert_eq!(TABLE_R[0x80], 0xe100);
}
#[test]
fn test_gcm_aes_block_mul_with_m0_r() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
let h = u128::from_be_bytes(h_block);
let m0 = calculate_table_m(h, 0);
let x_block = [
0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
0xf0, 0xfb,
];
let x = u128::from_be_bytes(x_block);
let r1 = block_mul_with_m0_r(&m0, x);
let r2 = block_mul(h, x);
assert_eq!(r1, r2);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let p = [
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::M0TableAndRTable.to_mul_fn(&cipher_key);
let reader = Cursor::new(&p);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let cipher_text = writer.into_inner();
assert_eq!(
&cipher_text,
&[
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
]
);
assert_eq!(
&tag,
&[
0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
0xfa, 0xb4
]
);
}
#[test]
fn test_gcm_aes_128_decrypt() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let cipher_text = [];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(&p, &[]);
assert_eq!(
&tag,
&[
0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7,
0x45, 0x5a
]
);
let cipher_text = [
0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2,
0xfe, 0x78,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
]
);
assert_eq!(
&tag,
&[
0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57,
0xbd, 0xdf
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let cipher_text = [
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
];
let aad = [];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55
]
);
assert_eq!(
&tag,
&[
0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
0xfa, 0xb4
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let cipher_text = [
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12,
0x1a, 0x47
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let cipher_text = [
0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a,
0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9,
0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09,
0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
0xc2, 0x3f, 0x45, 0x98,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2,
0xfc, 0xcb
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08,
];
let iv = [
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b,
];
let cipher_text = [
0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f,
0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c,
0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc,
0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
0x4c, 0x34, 0xae, 0xe5,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99,
0xd0, 0x50
]
);
}
#[test]
fn test_gcm_aes_256_decrypt() {
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let cipher_text = [];
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(&p, &[]);
assert_eq!(
&tag,
&[
0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb,
0x73, 0x8b
]
);
let cipher_key = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let iv = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let cipher_text = [
0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3,
0x9d, 0x18,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
]
);
assert_eq!(
&tag,
&[
0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a,
0xb9, 0x19
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let cipher_text = [
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
];
let aad = [];
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55
]
);
assert_eq!(
&tag,
&[
0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3,
0xcc, 0x6c
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
];
let cipher_text = [
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d,
0x55, 0x1b
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let cipher_text = [
0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98,
0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7,
0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c,
0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
0xf4, 0x7c, 0x9b, 0x1f,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e,
0xa8, 0xf2
]
);
let cipher_key = [
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
0x67, 0x30, 0x83, 0x08,
];
let iv = [
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b,
];
let cipher_text = [
0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e,
0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f,
0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3,
0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
0x44, 0xae, 0x7e, 0x3f,
];
let aad = [
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
];
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
let reader = Cursor::new(&cipher_text);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
let p = writer.into_inner();
assert_eq!(
&p,
&[
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
]
);
assert_eq!(
&tag,
&[
0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9,
0xf1, 0x9a
]
);
}
#[test]
fn test_input_validation_key_size() {
let invalid_key = [0u8; 8]; let iv = [0xca, 0xfe, 0xba, 0xbe];
let reader = Cursor::new(b"test");
let mut writer = Cursor::new(Vec::new());
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&[0u8; 16]);
let result = block_on(gcm_aes_encrypt_async(&invalid_key, &iv, reader, &mut writer, &[], &mul_fn));
assert!(matches!(result, Err(AesGcmAsyncError::InvalidKeySize(8))));
}
#[test]
fn test_input_validation_iv_size() {
let key = [0u8; 16];
let invalid_iv = [0u8; 0]; let reader = Cursor::new(b"test");
let mut writer = Cursor::new(Vec::new());
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
let result = block_on(gcm_aes_encrypt_async(&key, &invalid_iv, reader, &mut writer, &[], &mul_fn));
assert!(matches!(result, Err(AesGcmAsyncError::InvalidIvSize(0))));
}
#[test]
fn test_input_validation_iv_large_allowed() {
let key = [0u8; 16];
let large_iv = [0u8; 60]; let reader = Cursor::new(b"test");
let mut writer = Cursor::new(Vec::new());
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
let result = block_on(gcm_aes_encrypt_async(&key, &large_iv, reader, &mut writer, &[], &mul_fn));
assert!(result.is_ok()); }
#[test]
fn test_valid_key_sizes() {
let iv = [0xca, 0xfe, 0xba, 0xbe];
let plaintext = b"test data";
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&[0u8; 16]);
let key_128 = [0u8; 16];
let reader = Cursor::new(plaintext);
let mut writer = Cursor::new(Vec::new());
let result = block_on(gcm_aes_encrypt_async(&key_128, &iv, reader, &mut writer, &[], &mul_fn));
assert!(result.is_ok());
let key_192 = [0u8; 24];
let mul_fn_192 = GcmBlockMulEnhancement::None.to_mul_fn(&key_192);
let reader = Cursor::new(plaintext);
let mut writer = Cursor::new(Vec::new());
let result = block_on(gcm_aes_encrypt_async(&key_192, &iv, reader, &mut writer, &[], &mul_fn_192));
assert!(result.is_ok());
let key_256 = [0u8; 32];
let mul_fn_256 = GcmBlockMulEnhancement::None.to_mul_fn(&key_256);
let reader = Cursor::new(plaintext);
let mut writer = Cursor::new(Vec::new());
let result = block_on(gcm_aes_encrypt_async(&key_256, &iv, reader, &mut writer, &[], &mul_fn_256));
assert!(result.is_ok());
}
#[test]
fn test_encrypt_decrypt_roundtrip() {
let key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let plaintext = b"Hello, World! This is a test message for AES-GCM encryption.";
let aad = b"additional authenticated data";
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
let reader = Cursor::new(plaintext);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
let ciphertext = writer.into_inner();
let reader = Cursor::new(&ciphertext);
let mut writer = Cursor::new(Vec::new());
let computed_tag = block_on(gcm_aes_decrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
let decrypted = writer.into_inner();
assert_eq!(plaintext, &decrypted[..]);
assert_eq!(tag, computed_tag);
}
#[test]
fn test_authentication_failure() {
let key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
let plaintext = b"test message";
let aad = b"aad";
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
let reader = Cursor::new(plaintext);
let mut writer = Cursor::new(Vec::new());
let tag = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
let mut ciphertext = writer.into_inner();
ciphertext[0] ^= 1;
let reader = Cursor::new(&ciphertext);
let mut writer = Cursor::new(Vec::new());
let computed_tag = block_on(gcm_aes_decrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
assert_ne!(tag, computed_tag);
}
#[test]
fn test_large_data_performance() {
let key = [0u8; 16];
let iv = [0xca, 0xfe, 0xba, 0xbe];
let plaintext = vec![0x42u8; 1024 * 1024]; let aad = b"large data test";
let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
let reader = Cursor::new(&plaintext);
let mut writer = Cursor::new(Vec::new());
let start = std::time::Instant::now();
let result = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn));
let duration = start.elapsed();
assert!(result.is_ok());
assert!(duration.as_millis() < 5000); assert_eq!(writer.into_inner().len(), plaintext.len());
}
#[test]
fn test_error_display_formatting() {
let key_error = AesGcmAsyncError::InvalidKeySize(8);
assert_eq!(format!("{}", key_error), "Invalid key size: 8 bytes. Must be 16, 24, or 32 bytes");
let iv_error = AesGcmAsyncError::InvalidIvSize(0);
assert_eq!(format!("{}", iv_error), "Invalid IV size: 0 bytes. Must be at least 1 byte (longer IVs are hashed to 12 bytes)");
let auth_error = AesGcmAsyncError::AuthenticationFailed;
assert_eq!(format!("{}", auth_error), "Authentication failed - message may be corrupted or tampered with");
}
}