From 4e9f7c031cdb018dfec15c3dc86eaff80fa52897 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sun, 27 Aug 2023 16:00:15 +0800 Subject: [PATCH] feat: add zeroize and rename next to update --- Cargo.toml | 5 ++- src/decryptor.rs | 4 +- src/encryptor.rs | 4 +- src/lib.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++--- src/util.rs | 8 ++-- 5 files changed, 120 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bca0b5f..fbc525e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,8 @@ edition = "2021" [dependencies] aes = { version = "0.8.3", features = ["zeroize"] } -aes-gcm = { version = "0.10.2", features = ["zeroize"] } hex = "0.4.3" +zeroize = { version = "1.6.0", features = ["zeroize_derive"] } + +[dev-dependencies] +aes-gcm = { version = "0.10.2", features = ["zeroize"] } diff --git a/src/decryptor.rs b/src/decryptor.rs index b821922..0fc6d72 100644 --- a/src/decryptor.rs +++ b/src/decryptor.rs @@ -1,6 +1,7 @@ use aes::{Aes128, Aes192, Aes256}; use aes::cipher::{Block, BlockEncrypt, KeyInit}; use aes::cipher::generic_array::GenericArray; +use zeroize::ZeroizeOnDrop; use crate::util::{gmul_128, inc_32, msb_s, normalize_nonce, u8to128}; @@ -11,6 +12,7 @@ macro_rules! define_aes_gcm_stream_decryptor_impl { $key_size:tt ) => { +#[derive(ZeroizeOnDrop)] pub struct $module { crypto: $aesn, message_buffer: Vec, @@ -55,7 +57,7 @@ impl $module { self.integrality_buffer.extend_from_slice(&vec![0x00; v / 8]); } - pub fn next(&mut self, bytes: &[u8]) -> Vec { + pub fn update(&mut self, bytes: &[u8]) -> Vec { self.message_buffer.extend_from_slice(bytes); let message_buffer_slice = self.message_buffer.as_slice(); let message_buffer_len = message_buffer_slice.len(); diff --git a/src/encryptor.rs b/src/encryptor.rs index d42a6ef..9fa4f32 100644 --- a/src/encryptor.rs +++ b/src/encryptor.rs @@ -1,6 +1,7 @@ use aes::{Aes128, Aes192, Aes256}; use aes::cipher::{Block, BlockEncrypt, KeyInit}; use aes::cipher::generic_array::GenericArray; +use zeroize::ZeroizeOnDrop; use crate::util::{gmul_128, inc_32, msb_s, normalize_nonce, u8to128}; @@ -11,6 +12,7 @@ macro_rules! define_aes_gcm_stream_encryptor_impl { $key_size:tt ) => { +#[derive(ZeroizeOnDrop)] pub struct $module { crypto: $aesn, message_buffer: Vec, @@ -55,7 +57,7 @@ impl $module { self.integrality_buffer.extend_from_slice(&vec![0x00; v / 8]); } - pub fn next(&mut self, bytes: &[u8]) -> Vec { + pub fn update(&mut self, bytes: &[u8]) -> Vec { self.message_buffer.extend_from_slice(bytes); let message_buffer_slice = self.message_buffer.as_slice(); let message_buffer_len = message_buffer_slice.len(); diff --git a/src/lib.rs b/src/lib.rs index c2eb352..58bc925 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,7 @@ fn test128() { if !aad.is_empty() { encryptor.init_adata(aad); } - ciphertext.extend_from_slice(&encryptor.next(plaintext)); + ciphertext.extend_from_slice(&encryptor.update(plaintext)); let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); @@ -64,7 +64,7 @@ fn test128() { if !aad.is_empty() { decryptor.init_adata(aad); } - let mut plaintext1 = decryptor.next(ciphertext.as_slice()); + 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()); @@ -88,6 +88,67 @@ fn test128() { } } +#[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}; @@ -132,7 +193,7 @@ fn test256() { if !aad.is_empty() { encryptor.init_adata(aad); } - ciphertext.extend_from_slice(&encryptor.next(plaintext)); + ciphertext.extend_from_slice(&encryptor.update(plaintext)); let (last_block, tag) = encryptor.finalize(); ciphertext.extend_from_slice(&last_block); ciphertext.extend_from_slice(&tag); @@ -142,7 +203,7 @@ fn test256() { if !aad.is_empty() { decryptor.init_adata(aad); } - let mut plaintext1 = decryptor.next(ciphertext.as_slice()); + 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()); @@ -164,4 +225,45 @@ fn test256() { }; assert_eq!(plaintext, decrypted_plaintext.as_slice()); } -} \ No newline at end of file +} + +#[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..1024 { + 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()); +} diff --git a/src/util.rs b/src/util.rs index ea23b3d..8b403bc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -19,8 +19,8 @@ pub(crate) fn gmul_128(x: u128, y: u128) -> u128 { pub(crate) fn ghash(key: u128, messages: &[u128]) -> u128 { let mut y = 0u128; - for i in 0..messages.len() { - let yi = gmul_128(y ^ messages[i], key); + for message in messages { + let yi = gmul_128(y ^ message, key); y = yi; } y @@ -54,9 +54,7 @@ pub(crate) fn msb_s(s: usize, bytes: &[u8]) -> Vec { let mut result = vec![]; let n = s / 8; let remain = s % 8; - for i in 0..n { - result.push(bytes[i]); - } + result.extend_from_slice(&bytes[0..n]); if remain > 0 { result.push(bytes[n] >> (8 - remain)); }