From 15ae77b719d3ca74d3ba502bd616cdf9cfc7bd36 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Thu, 27 Apr 2023 18:37:59 -0700 Subject: [PATCH] Pre set 2 refactors --- examples/set1_5/main.rs | 2 +- examples/set1_7/main.rs | 10 ++--- src/friendly.rs | 21 ++++++++++ src/lib.rs | 2 + src/prelude.rs | 86 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 src/friendly.rs diff --git a/examples/set1_5/main.rs b/examples/set1_5/main.rs index 782374c..f96932c 100644 --- a/examples/set1_5/main.rs +++ b/examples/set1_5/main.rs @@ -3,7 +3,7 @@ use cryptopals::{prelude::*, bvec}; fn main() { let input = Vec::from_text( "Burning 'em, if you ain't quick and nimble -I go crazy when I hear a cymbal"); +I go crazy when I hear a cymbal").unwrap(); let output = bvec!("output.txt"); assert_eq!(input.xor_repeating(&b"ICE".to_vec()).unwrap(), output); diff --git a/examples/set1_7/main.rs b/examples/set1_7/main.rs index 72c9901..dfc1866 100644 --- a/examples/set1_7/main.rs +++ b/examples/set1_7/main.rs @@ -1,17 +1,13 @@ #![feature(array_chunks)] -use aes::{cipher::{KeyInit, generic_array::GenericArray, Key, BlockEncrypt, BlockDecrypt}, Aes128, Block}; -use cryptopals::{prelude::*, bvec, bvec64}; +use cryptopals::{prelude::*, bvec, bvec64, friendly::aes128}; fn main() { - let key: Key = GenericArray::from(*b"YELLOW SUBMARINE"); - let aes = aes::Aes128::new(&key); + let key = *b"YELLOW SUBMARINE"; let input = bvec64!("input.txt"); let mut output = Vec::new(); for chunk in input.array_chunks::<16>() { - let mut block: Block = GenericArray::from(*chunk); - aes.decrypt_block(&mut block); - output.extend(<[u8; 16]>::from(block)); + output.extend(aes128::decrypt(key, *chunk)); } dbg!(output.to_text().unwrap()); diff --git a/src/friendly.rs b/src/friendly.rs new file mode 100644 index 0000000..df9cd62 --- /dev/null +++ b/src/friendly.rs @@ -0,0 +1,21 @@ +pub mod aes128 { + use aes::cipher::{generic_array::GenericArray, KeyInit, BlockEncrypt, BlockDecrypt}; + + pub fn encrypt(key: [u8; 16], block: [u8; 16]) -> [u8; 16] { + let key = GenericArray::from(key); + let aes = aes::Aes128::new(&key); + + let mut block = GenericArray::from(block); + aes.encrypt_block(&mut block); + <[u8; 16]>::from(block) + } + + pub fn decrypt(key: [u8; 16], block: [u8; 16]) -> [u8; 16] { + let key = GenericArray::from(key); + let aes = aes::Aes128::new(&key); + + let mut block = GenericArray::from(block); + aes.decrypt_block(&mut block); + <[u8; 16]>::from(block) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ce3506c..c11d88b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ +#![feature(array_chunks)] +pub mod friendly; pub mod english; pub mod prelude; \ No newline at end of file diff --git a/src/prelude.rs b/src/prelude.rs index 0be0e94..b4858ad 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -25,6 +25,7 @@ macro_rules! bvecs { #[derive(Debug)] pub enum PreludeError { + WrongLength(usize), B64Err(base64::DecodeError), FHErr(hex::FromHexError), Utf8Err(std::str::Utf8Error), @@ -40,13 +41,16 @@ pub trait ByteBased: Sized { fn from_b64(b: &str) -> CPals; fn to_b64(&self) -> String; - fn from_text(t: &str) -> Self; + fn from_text(t: &str) -> CPals; fn to_text(&self) -> CPals<&str>; fn xor_with(&self, other: &Self) -> CPals; fn xor_repeating(&self, other: &Self) -> CPals; fn hamming(&self, other: &Self) -> CPals; + + fn to_fixed_len(&self) -> CPals<[u8; N]>; + fn to_variable_len(&self) -> Vec; } impl ByteBased for Vec { @@ -66,8 +70,8 @@ impl ByteBased for Vec { base64::engine::general_purpose::STANDARD.encode(self) } - fn from_text(tx: &str) -> Self { - tx.as_bytes().to_vec() + fn from_text(tx: &str) -> CPals { + Ok(tx.as_bytes().to_vec()) } fn to_text(&self) -> CPals<&str> { @@ -102,8 +106,84 @@ impl ByteBased for Vec { } Ok(bdist) } + + fn to_fixed_len(&self) -> CPals<[u8; N]> { + if self.len() != N { + return Err(PreludeError::WrongLength(self.len())) + } + // avoid the owned requirement for [u8; N] + Ok(*self.array_chunks().next().unwrap()) + } + + fn to_variable_len(&self) -> Vec { + self.clone() + } } +impl ByteBased for [u8; N] { + fn from_hex(h: &str) -> CPals { + let v = >::from_hex(h)?; + v.to_fixed_len() + } + + fn to_hex(&self) -> String { + self.to_variable_len().to_hex() + } + + fn from_b64(b: &str) -> CPals { + let v = >::from_b64(b)?; + v.to_fixed_len() + } + + fn to_b64(&self) -> String { + self.to_variable_len().to_b64() + } + + fn from_text(t: &str) -> CPals { + let v = >::from_text(t)?; + v.to_fixed_len() + } + + fn to_text(&self) -> CPals<&str> { + std::str::from_utf8(self).map_err(PreludeError::Utf8Err) + } + + fn xor_with(&self, other: &Self) -> CPals { + let mut result = [0; N]; + for i in 0..N { + result[i] = self[i] ^ other[i]; + } + Ok(result) + } + + fn xor_repeating(&self, other: &Self) -> CPals { + self.xor_with(other) // they necessarily have the same length + } + + fn hamming(&self, other: &Self) -> CPals { + let mut count: u64 = 0; + + for i in 0..N { + count += (self[i] ^ other[i]).count_ones() as u64; + } + + Ok(count) + } + + fn to_fixed_len(&self) -> CPals<[u8; N2]> { + let slice: &[u8] = self; + if let Ok(x) = <&[u8; N2]>::try_from(slice) { + return Ok(*x) + } + return Err(PreludeError::WrongLength(self.len())) + } + + fn to_variable_len(&self) -> Vec { + self.to_vec() + } +} + + pub fn remove_ws(s: &str) -> String { let mut new = String::with_capacity(s.len()); for c in s.chars() {