diff --git a/Cargo.toml b/Cargo.toml index fb75112..b1440e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aes-gcm-stream" -version = "0.2.1" +version = "0.2.2" edition = "2021" authors = ["Hatter Jiang"] repository = "https://git.hatter.ink/hatter/aes-gcm-stream" diff --git a/src/lib.rs b/src/lib.rs index 1067d73..a8d6f36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,27 +24,81 @@ mod util; mod encryptor; mod decryptor; -pub fn aes_256_gcm_decrypt(key: &[u8], nonce: &[u8], message: &[u8]) -> Result, String> { - let mut key: [u8; 32] = match key.try_into() { - Err(_) => return Err(format!("Bad key length")), - Ok(key) => key, - }; - let mut aes256_gcm = Aes256GcmStreamDecryptor::new(key, nonce); - let mut first_block = aes256_gcm.update(message); - let final_block = aes256_gcm.finalize()?; +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] = match key.try_into() { - Err(_) => return Err(format!("Bad key length")), - Ok(key) => key, - }; - let mut aes256_gcm = Aes256GcmStreamEncryptor::new(key, nonce); - let mut first_block = aes256_gcm.update(message); - let (last_block, tag) = aes256_gcm.finalize(); + 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(); @@ -309,6 +363,62 @@ fn test256_stream() { 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]; @@ -328,7 +438,11 @@ fn test256_stream_and_array() { 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); }