diff --git a/Cargo.toml b/Cargo.toml index 93d017a..8d5954a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ aes = "0.6.0" block-modes = "0.7.0" simple-error = "0.2.3" hex = "0.4.2" +num-traits = "0.2.14" +num-derive = "0.3.3" +rand = "0.8.3" [dev-dependencies] hex-literal = "0.3.1" \ No newline at end of file diff --git a/src/crypto/cipher/aes.rs b/src/crypto/cipher/aes.rs index 17bb6b5..aaa865d 100644 --- a/src/crypto/cipher/aes.rs +++ b/src/crypto/cipher/aes.rs @@ -2,30 +2,37 @@ use aes::Aes128; use block_modes::{BlockMode, Cbc}; use block_modes::block_padding::NoPadding; use crate::error::{Result, Error}; +use super::Cipher; type Aes128Cbc = Cbc; -pub const KEY_LEN: usize = 16; +pub struct AES {} -pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = Aes128Cbc::new_var(&key, &iv)?; +impl Cipher for AES { + const BLOCK_SIZE: usize = 16; + const KEY_SIZE: usize = 16; - return Ok(cipher.encrypt_vec(data)); -} + fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = Aes128Cbc::new_var(&key, &iv)?; -pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = Aes128Cbc::new_var(&key, &iv)?; + return Ok(cipher.encrypt_vec(data)); + } - let result = cipher.decrypt_vec(data); - return match result { - Ok(data) => {Ok(data)} - Err(err) => {Err(Error::BlockModeError(err))} + fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = Aes128Cbc::new_var(&key, &iv)?; + + let result = cipher.decrypt_vec(data); + return match result { + Ok(data) => { Ok(data) } + Err(err) => { Err(Error::BlockModeError(err)) } + } } } #[cfg(test)] mod tests { use hex_literal::hex; + use crate::crypto::cipher::Cipher; #[test] fn encrypt() { @@ -33,7 +40,7 @@ mod tests { let key = hex!("e7aff3361c3e85347993c3219a87d24b"); let iv = hex!("00000000000000000000000000000000"); - let data_enc = crate::crypto::cipher::aes::encrypt(&data, key, &iv).unwrap(); + let data_enc = crate::crypto::cipher::aes::AES::encrypt(&data, &key, &iv).unwrap(); let data_enc_expected = hex!("3c79d74a4969ba7123e5d8f6df24493112d221fd131a4617d0eda5d92ccc1b46"); diff --git a/src/crypto/cipher/mod.rs b/src/crypto/cipher/mod.rs index 4cf755d..aa04bec 100644 --- a/src/crypto/cipher/mod.rs +++ b/src/crypto/cipher/mod.rs @@ -6,7 +6,10 @@ pub mod tdes_3k; use crate::error::Result; //TODO: impl this for all the ciphers -trait Cipher { +pub trait Cipher { + const BLOCK_SIZE: usize; + const KEY_SIZE: usize; + fn encrypt (data: &[u8], key: &[u8], iv: &[u8]) -> Result>; fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result>; } \ No newline at end of file diff --git a/src/crypto/cipher/tdes.rs b/src/crypto/cipher/tdes.rs index 29ffcbc..d403831 100644 --- a/src/crypto/cipher/tdes.rs +++ b/src/crypto/cipher/tdes.rs @@ -3,31 +3,38 @@ use des::TdesEde2; use block_modes::{BlockMode, Cbc}; use block_modes::block_padding::NoPadding; use crate::error::{Result, Error}; +use crate::crypto::cipher::Cipher; type TDesEde2Cbc = Cbc; -pub const KEY_LEN: usize = 16; +pub struct Tdes {} -pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde2Cbc::new_var(&key, &iv)?; +impl Cipher for Tdes { + const BLOCK_SIZE: usize = 8; + const KEY_SIZE: usize = 16; - return Ok(cipher.encrypt_vec(data)); -} + fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde2Cbc::new_var(&key, &iv)?; -pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde2Cbc::new_var(&key, &iv)?; + return Ok(cipher.encrypt_vec(data)); + } + + fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde2Cbc::new_var(&key, &iv)?; - let result = cipher.decrypt_vec(data); - return match result { - Ok(data) => {Ok(data)} - Err(err) => {Err(Error::BlockModeError(err))} + let result = cipher.decrypt_vec(data); + return match result { + Ok(data) => { Ok(data) } + Err(err) => { Err(Error::BlockModeError(err)) } + } } } #[cfg(test)] mod tests { use hex_literal::hex; + use crate::crypto::cipher::Cipher; #[test] #[ignore] @@ -36,7 +43,7 @@ mod tests { let key = hex!("00000000000000000000000000000000"); let iv = hex!("00000000000000000000000000000000"); - let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap(); + let data_enc = crate::crypto::cipher::tdes::Tdes::encrypt(&data, &key, &iv).unwrap(); let data_enc_expected = hex!(""); diff --git a/src/crypto/cipher/tdes_2k.rs b/src/crypto/cipher/tdes_2k.rs index 29ffcbc..36fd602 100644 --- a/src/crypto/cipher/tdes_2k.rs +++ b/src/crypto/cipher/tdes_2k.rs @@ -3,31 +3,38 @@ use des::TdesEde2; use block_modes::{BlockMode, Cbc}; use block_modes::block_padding::NoPadding; use crate::error::{Result, Error}; +use crate::crypto::cipher::Cipher; type TDesEde2Cbc = Cbc; -pub const KEY_LEN: usize = 16; +pub struct Tdes2k {} -pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde2Cbc::new_var(&key, &iv)?; +impl Cipher for Tdes2k { + const BLOCK_SIZE: usize = 8; + const KEY_SIZE: usize = 16; - return Ok(cipher.encrypt_vec(data)); -} + fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde2Cbc::new_var(&key, &iv)?; -pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde2Cbc::new_var(&key, &iv)?; + return Ok(cipher.encrypt_vec(data)); + } + + fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde2Cbc::new_var(&key, &iv)?; - let result = cipher.decrypt_vec(data); - return match result { - Ok(data) => {Ok(data)} - Err(err) => {Err(Error::BlockModeError(err))} + let result = cipher.decrypt_vec(data); + return match result { + Ok(data) => { Ok(data) } + Err(err) => { Err(Error::BlockModeError(err)) } + } } } #[cfg(test)] mod tests { use hex_literal::hex; + use crate::crypto::cipher::Cipher; #[test] #[ignore] @@ -36,7 +43,7 @@ mod tests { let key = hex!("00000000000000000000000000000000"); let iv = hex!("00000000000000000000000000000000"); - let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap(); + let data_enc = crate::crypto::cipher::tdes_2k::Tdes2k::encrypt(&data, &key, &iv).unwrap(); let data_enc_expected = hex!(""); diff --git a/src/crypto/cipher/tdes_3k.rs b/src/crypto/cipher/tdes_3k.rs index 972f964..a31d85d 100644 --- a/src/crypto/cipher/tdes_3k.rs +++ b/src/crypto/cipher/tdes_3k.rs @@ -3,31 +3,38 @@ use des::TdesEde3; use block_modes::{BlockMode, Cbc}; use block_modes::block_padding::NoPadding; use crate::error::{Result, Error}; +use crate::crypto::cipher::Cipher; type TDesEde3Cbc = Cbc; -pub const KEY_LEN: usize = 24; +pub struct Tdes3k {} -pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde3Cbc::new_var(&key, &iv)?; +impl Cipher for Tdes3k { + const BLOCK_SIZE: usize = 8; + const KEY_SIZE: usize = 24; - return Ok(cipher.encrypt_vec(data)); -} + fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde3Cbc::new_var(&key, &iv)?; -pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result> { - let cipher = TDesEde3Cbc::new_var(&key, &iv)?; + return Ok(cipher.encrypt_vec(data)); + } + + fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result> { + let cipher = TDesEde3Cbc::new_var(&key, &iv)?; - let result = cipher.decrypt_vec(data); - return match result { - Ok(data) => {Ok(data)} - Err(err) => {Err(Error::BlockModeError(err))} + let result = cipher.decrypt_vec(data); + return match result { + Ok(data) => { Ok(data) } + Err(err) => { Err(Error::BlockModeError(err)) } + } } } #[cfg(test)] mod tests { use hex_literal::hex; + use crate::crypto::cipher::Cipher; #[test] #[ignore] @@ -36,7 +43,7 @@ mod tests { let key = hex!("00000000000000000000000000000000"); let iv = hex!("00000000000000000000000000000000"); - let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap(); + let data_enc = crate::crypto::cipher::tdes_3k::Tdes3k::encrypt(&data, &key, &iv).unwrap(); let data_enc_expected = hex!(""); diff --git a/src/crypto/cipher_key.rs b/src/crypto/cipher_key.rs index b09dff0..2029f3b 100644 --- a/src/crypto/cipher_key.rs +++ b/src/crypto/cipher_key.rs @@ -1,6 +1,6 @@ use crate::crypto::cipher_type::CipherType; use crate::crypto::cipher_type::CipherType::*; -use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k}; +use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k, Cipher}; use crate::error::Error; use crate::error::Result; @@ -63,10 +63,10 @@ pub fn generate_empty_key(cipher: CipherType) -> Box<[u8]> { /// Get KeySize for CipherType pub fn get_key_size(cipher: CipherType) -> usize { match cipher { - TDES => tdes::KEY_LEN, - TDES2K => tdes_2k::KEY_LEN, - TDES3K => tdes_3k::KEY_LEN, - AES => aes::KEY_LEN + TDES => tdes::Tdes::KEY_SIZE, + TDES2K => tdes_2k::Tdes2k::KEY_SIZE, + TDES3K => tdes_3k::Tdes3k::KEY_SIZE, + AES => aes::AES::KEY_SIZE, } } diff --git a/src/crypto/crc/crc32.rs b/src/crypto/crc/crc32.rs index eb4ba39..fe09913 100644 --- a/src/crypto/crc/crc32.rs +++ b/src/crypto/crc/crc32.rs @@ -18,14 +18,14 @@ pub fn calculate_with_initial(data: &[u8], mut crc32: u32) -> u32 { crc32 } -pub fn calculate(data: &[u8]) -> Box<[u8]> { +pub fn calculate(data: &[u8]) -> Vec { let mut crc32 = INIT_VALUE; for d in data { crc32 = calculate_with_initial(from_ref(d), crc32); } - Box::new(crc32.to_ne_bytes()) + crc32.to_ne_bytes().to_vec() } #[cfg(test)] diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 3a47ec8..78915ab 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -1,4 +1,5 @@ pub mod cipher; pub mod crc; pub mod cipher_type; -pub mod cipher_key; \ No newline at end of file +pub mod cipher_key; +pub mod util; \ No newline at end of file diff --git a/src/crypto/util.rs b/src/crypto/util.rs new file mode 100644 index 0000000..cff4a8e --- /dev/null +++ b/src/crypto/util.rs @@ -0,0 +1,20 @@ +use crate::error::{Result, Error}; +use simple_error::simple_error; +use block_modes::block_padding::{ZeroPadding, Padding}; + +pub fn extract_last_block(data: &[u8], blocksize: usize) -> Result<&[u8]> { + if data.len() % blocksize != 0 { + return Err(simple_error!("Data is not compatible with blocksize: data(length): {}, blocksize: {}.", data.len(), blocksize).into()) + } + + Ok(&data[(data.len() - blocksize)..]) +} + +pub fn expand_to_blocksize(data: &mut [u8], blocksize: usize) -> Result<&mut [u8]> { + // let diff = data.len() % blocksize; + + match ZeroPadding::pad(data, data.len(), blocksize) { + Ok(x) => {Ok(x)} + Err(e) => {Err(Error::PadError(e))} + } +} \ No newline at end of file