From c5789b720d4367001b0e4dab6bca1d234be02ef6 Mon Sep 17 00:00:00 2001 From: SeungMin Lee Date: Wed, 22 Jan 2020 15:19:47 +0900 Subject: [PATCH 1/5] Add /target directory to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 03314f7..43e1cc2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ Cargo.lock + +# Generated by Cargo +**/target/ \ No newline at end of file From ff16500f6eeab23d39b547f11434d40c2eb4e27e Mon Sep 17 00:00:00 2001 From: SeungMin Lee Date: Thu, 30 Jan 2020 17:58:49 +0900 Subject: [PATCH 2/5] Replace hash crates to other crates --- Cargo.toml | 5 +++++ src/hash.rs | 36 ++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 82b3d21..2c6f006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,11 @@ ring = "0.14.6" quick-error = "1.2" rust-crypto = "0.2.36" primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" } +sha-1 = "0.8.2" +sha2 = "0.8.1" +sha3 = "0.8.2" +ripemd160 = "0.8.0" +digest = "0.8" [dev-dependencies] rand = "0.6.1" diff --git a/src/hash.rs b/src/hash.rs index f258d3d..38a871c 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -14,55 +14,55 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use digest::Digest; use primitives::{H160, H256}; -use rcrypto::digest::Digest; -use rcrypto::ripemd160::Ripemd160; -use rcrypto::sha1::Sha1; -use rcrypto::sha2::Sha256; -use rcrypto::sha3::Sha3; +use ripemd160::Ripemd160; +use sha1::Sha1; +use sha2::Sha256; +use sha3::Keccak256; /// RIPEMD160 #[inline] pub fn ripemd160>(s: T) -> H160 { let input = s.as_ref(); - let mut result = H160::default(); let mut hasher = Ripemd160::new(); hasher.input(input); - hasher.result(&mut *result); - result + let mut array: [u8; 20] = [0; 20]; + array.copy_from_slice(&hasher.result()); + H160(array) } /// SHA-1 #[inline] pub fn sha1>(s: T) -> H160 { let input = s.as_ref(); - let mut result = H160::default(); let mut hasher = Sha1::new(); hasher.input(input); - hasher.result(&mut *result); - result + let mut array: [u8; 20] = [0; 20]; + array.copy_from_slice(&hasher.result()); + H160(array) } /// SHA-256 #[inline] pub fn sha256>(s: T) -> H256 { let input = s.as_ref(); - let mut result = H256::default(); let mut hasher = Sha256::new(); hasher.input(input); - hasher.result(&mut *result); - result + let mut array: [u8; 32] = [0; 32]; + array.copy_from_slice(&hasher.result()); + H256(array) } /// KECCAK256 #[inline] pub fn keccak256>(s: T) -> H256 { let input = s.as_ref(); - let mut result = H256::default(); - let mut hasher = Sha3::keccak256(); + let mut hasher = Keccak256::new(); hasher.input(input); - hasher.result(&mut result); - result + let mut array: [u8; 32] = [0; 32]; + array.copy_from_slice(&hasher.result()); + H256(array) } #[cfg(test)] From 81425848a3841c2650b124c53d14ba92cef09c68 Mon Sep 17 00:00:00 2001 From: SeungMin Lee Date: Thu, 30 Jan 2020 18:08:44 +0900 Subject: [PATCH 3/5] Replace the blake crate to other crate --- Cargo.toml | 1 + src/blake.rs | 29 ++++++++++++----------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c6f006..d4e6eff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ sha2 = "0.8.1" sha3 = "0.8.2" ripemd160 = "0.8.0" digest = "0.8" +blake2 = "0.8.1" [dev-dependencies] rand = "0.6.1" diff --git a/src/blake.rs b/src/blake.rs index 27324fc..63edd46 100644 --- a/src/blake.rs +++ b/src/blake.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use blake2::digest::{Input, VariableOutput}; +use blake2::VarBlake2b; use primitives::{H128, H160, H256, H512}; -use rcrypto::blake2b::Blake2b; -use rcrypto::digest::Digest; /// BLAKE128 pub fn blake128>(s: T) -> H128 { @@ -51,32 +51,27 @@ pub trait Blake { } macro_rules! implement_blake { - ($self:ident) => { + ($self:ident, $size:expr) => { impl Blake for $self { fn blake>(s: T) -> Self { - let input = s.as_ref(); - let mut result = Self::default(); - let mut hasher = Blake2b::new(result.len()); - hasher.input(input); - hasher.result(&mut *result); - result + Self::blake_with_key(s, &[]) } fn blake_with_key>(s: T, key: &[u8]) -> Self { let input = s.as_ref(); - let mut result = Self::default(); - let mut hasher = Blake2b::new_keyed(result.len(), &key); + let mut hasher = VarBlake2b::new_keyed(&key, $size); hasher.input(input); - hasher.result(&mut *result); - result + let mut result: [u8; $size] = [0; $size]; + result.copy_from_slice(&hasher.vec_result()); + Self(result) } } }; } -implement_blake!(H128); -implement_blake!(H160); -implement_blake!(H256); -implement_blake!(H512); +implement_blake!(H128, 16); +implement_blake!(H160, 20); +implement_blake!(H256, 32); +implement_blake!(H512, 64); /// Get the 256-bits BLAKE2b hash of the empty bytes string. pub const BLAKE_EMPTY: H256 = H256([ From da90429eecdf972c9ee67730781ec1033049fce0 Mon Sep 17 00:00:00 2001 From: SeungMin Lee Date: Thu, 30 Jan 2020 18:10:02 +0900 Subject: [PATCH 4/5] Replace crates related to the 256-CBC and 128-CTR mode to other crates --- Cargo.toml | 4 +++ src/aes.rs | 99 ++++++++++++++++++++++++++++------------------------ src/error.rs | 7 ++-- 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d4e6eff..258434c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,10 @@ sha3 = "0.8.2" ripemd160 = "0.8.0" digest = "0.8" blake2 = "0.8.1" +block-modes = "0.3.3" +aes = "0.3.2" +ctr = "0.3.2" +hex = "0.4.0" [dev-dependencies] rand = "0.6.1" diff --git a/src/aes.rs b/src/aes.rs index be2d6a9..1cad8db 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -14,59 +14,35 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use aes::{Aes128, Aes256}; +use block_modes::block_padding::Pkcs7; +use block_modes::InvalidKeyIvLength; +use block_modes::{BlockMode, Cbc}; +use ctr; +use ctr::stream_cipher::generic_array::GenericArray; +use ctr::stream_cipher::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek}; use primitives::H256; -use rcrypto::aes::KeySize::KeySize256; -use rcrypto::aes::{cbc_decryptor, cbc_encryptor}; -use rcrypto::aessafe::AesSafe128Encryptor; -use rcrypto::blockmodes::{CtrMode, PkcsPadding}; -use rcrypto::buffer::{BufferResult, ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer}; -pub use rcrypto::symmetriccipher::SymmetricCipherError; -use rcrypto::symmetriccipher::{Decryptor, Encryptor}; use super::error::SymmError; -fn is_underflow(result: BufferResult) -> bool { - match result { - BufferResult::BufferUnderflow => true, - BufferResult::BufferOverflow => false, - } -} - -// AES-256/CBC/Pkcs encryption. -pub fn encrypt(data: &[u8], key: &H256, iv: &u128) -> Result, SymmetricCipherError> { - let mut encryptor = cbc_encryptor(KeySize256, key, &iv.to_be_bytes(), PkcsPadding); - - let mut final_result = Vec::::new(); - let mut read_buffer = RefReadBuffer::new(data); - let mut buffer = [0; 4096]; - let mut write_buffer = RefWriteBuffer::new(&mut buffer); +type Aes256Cbc = Cbc; +type Aes128Ctr = ctr::Ctr128; - let mut finish = false; - while !finish { - finish = is_underflow(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?); - final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned()); - } +// AES-256/CBC/Pkcs encryption. +pub fn encrypt(data: &[u8], key: &H256, iv: &u128) -> Result, InvalidKeyIvLength> { + let cipher = Aes256Cbc::new_var(&key, &iv.to_be_bytes())?; + let result = cipher.encrypt_vec(data); - Ok(final_result) + Ok(result) } // AES-256/CBC/Pkcs decryption. -pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result, SymmetricCipherError> { - let mut decryptor = cbc_decryptor(KeySize256, key, &iv.to_be_bytes(), PkcsPadding); - - let mut final_result = Vec::::new(); - let mut read_buffer = RefReadBuffer::new(encrypted_data); - let mut buffer = [0; 4096]; - let mut write_buffer = RefWriteBuffer::new(&mut buffer); - - let mut finish = false; - while !finish { - finish = is_underflow(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?); - final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned()); - } +pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result, InvalidKeyIvLength> { + let cipher = Aes256Cbc::new_var(&key, &iv.to_be_bytes())?; + let result = cipher.decrypt_vec(&encrypted_data.to_vec()).unwrap(); - Ok(final_result) + Ok(result) } /// Encrypt a message (CTR mode). @@ -74,8 +50,9 @@ pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result, /// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. /// An error is returned if the input lengths are invalid. pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); - encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true)?; + let mut cipher = Aes128Ctr::new(&GenericArray::from_slice(k), &GenericArray::from_slice(iv)); + dest.copy_from_slice(plain); + cipher.apply_keystream(dest); Ok(()) } @@ -84,8 +61,10 @@ pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Re /// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. /// An error is returned if the input lengths are invalid. pub fn decrypt_128_ctr(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); - encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true)?; + let mut cipher = Aes128Ctr::new(&GenericArray::from_slice(k), &GenericArray::from_slice(iv)); + dest.copy_from_slice(encrypted); + cipher.seek(0); + cipher.apply_keystream(dest); Ok(()) } @@ -146,4 +125,32 @@ mod tests { let decrypted = decrypt(&encrypted, &key, &iv).unwrap(); assert_eq!(input, decrypted); } + + #[test] + fn aes_256_cbc_encrypt_decrypt() { + let message = [1, 2, 3, 4, 5, 6, 7, 8]; + let key = H256([0; 32]); + let iv = 0; + + let encrypted_data = encrypt(&message, &key, &iv).ok().unwrap(); + assert_eq!(encrypted_data, [45, 34, 87, 122, 38, 50, 190, 242, 253, 245, 138, 7, 196, 24, 58, 91]); + + let decrypted_data = decrypt(&encrypted_data[..], &key, &iv).ok().unwrap(); + assert_eq!(message, &decrypted_data[..]); + } + + #[test] + fn aes_128_ctr_encrypt_decrypt() { + let plaintext = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let key = [1; 16]; + let iv = [1; 16]; + let mut dest = [0; 10]; + + let _ = encrypt_128_ctr(&key, &iv, &plaintext, &mut dest); + assert_eq!(dest, [94, 118, 231, 156, 139, 128, 146, 51, 129, 171]); + + let ciphertext = dest; + let _ = decrypt_128_ctr(&key, &iv, &ciphertext, &mut dest); + assert_eq!(plaintext, dest); + } } diff --git a/src/error.rs b/src/error.rs index 6677c1b..1d94ad0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -47,13 +47,12 @@ quick_error! { #[allow(deprecated)] mod errors { - use rcrypto; use ring; quick_error! { #[derive(Debug)] pub enum SymmError wraps PrivSymmErr { - RustCrypto(e: rcrypto::symmetriccipher::SymmetricCipherError) { + RustCrypto(e: block_modes::InvalidKeyIvLength) { display("symmetric crypto error") from() } @@ -74,8 +73,8 @@ mod errors { } } - impl From for SymmError { - fn from(e: rcrypto::symmetriccipher::SymmetricCipherError) -> SymmError { + impl From for SymmError { + fn from(e: block_modes::InvalidKeyIvLength) -> SymmError { SymmError(PrivSymmErr::RustCrypto(e)) } } From a687270eaca77140177d4cd8683f725919518448 Mon Sep 17 00:00:00 2001 From: SeungMin Lee Date: Wed, 5 Feb 2020 14:30:52 +0900 Subject: [PATCH 5/5] Replace crates related to scrypt to other crates --- Cargo.toml | 2 +- src/error.rs | 19 +++++++++++++++++++ src/lib.rs | 1 - src/scrypt.rs | 40 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 258434c..093722b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] ring = "0.14.6" quick-error = "1.2" -rust-crypto = "0.2.36" primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" } sha-1 = "0.8.2" sha2 = "0.8.1" @@ -19,6 +18,7 @@ block-modes = "0.3.3" aes = "0.3.2" ctr = "0.3.2" hex = "0.4.0" +scrypt = { version = "0.2", default-features = false } [dev-dependencies] rand = "0.6.1" diff --git a/src/error.rs b/src/error.rs index 1d94ad0..56073c3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -42,11 +42,18 @@ quick_error! { InvalidP { display("Invalid p argument of the scrypt encryption") } + InvalidOutputLen { + display("Invalid length of output") + } + InvalidParams { + display("Invalid parameters") + } } } #[allow(deprecated)] mod errors { + use crate::error::ScryptError; use ring; quick_error! { @@ -78,5 +85,17 @@ mod errors { SymmError(PrivSymmErr::RustCrypto(e)) } } + + impl From for ScryptError { + fn from(_e: scrypt::errors::InvalidOutputLen) -> ScryptError { + ScryptError::InvalidOutputLen + } + } + + impl From for ScryptError { + fn from(_e: scrypt::errors::InvalidParams) -> ScryptError { + ScryptError::InvalidParams + } + } } pub use self::errors::SymmError; diff --git a/src/lib.rs b/src/lib.rs index eb487f5..4c62dc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,6 @@ // along with Parity. If not, see . -extern crate crypto as rcrypto; extern crate primitives; #[macro_use] extern crate quick_error; diff --git a/src/scrypt.rs b/src/scrypt.rs index 333f8b4..d18d40c 100644 --- a/src/scrypt.rs +++ b/src/scrypt.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use rcrypto::scrypt::{scrypt, ScryptParams}; +use scrypt::{scrypt, ScryptParams}; use crate::error::ScryptError; use crate::{Password, KEY_LENGTH, KEY_LENGTH_AES}; @@ -32,9 +32,43 @@ pub fn derive_key(pass: &Password, salt: &[u8; 32], n: u32, p: u32, r: u32) -> R } let mut derived_key = vec![0u8; KEY_LENGTH]; - let scrypt_params = ScryptParams::new(log_n, r, p); - scrypt(pass.as_bytes(), salt, &scrypt_params, &mut derived_key); + let scrypt_params = ScryptParams::new(log_n, r, p)?; + scrypt(pass.as_bytes(), salt, &scrypt_params, &mut derived_key)?; let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec())) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::password::Password; + + #[test] + fn scrypt_test() { + let mut password = Password("rust-crypto-codechain"); + let mut salt = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let mut n: u32 = 8; + let mut p: u32 = 16; + let mut r: u32 = 8; + + let mut result = derive_key(&password, &salt, n, p, r).unwrap(); + let mut right_bits = [229, 222, 150, 129, 167, 152, 151, 149, 110, 135, 118, 252, 139, 12, 227, 29]; + let mut left_bits = [111, 69, 216, 187, 101, 33, 114, 185, 126, 184, 57, 98, 243, 60, 174, 249]; + assert_eq!(&result.0[..], right_bits); + assert_eq!(&result.1[..], left_bits); + + + password = Password("Codechain and Foundry"); + salt = [0; 32]; + n = 16; + p = 1; + r = 1; + + result = derive_key(&password, &salt, n, p, r).unwrap(); + right_bits = [144, 79, 151, 99, 185, 187, 191, 74, 135, 222, 178, 102, 32, 179, 194, 170]; + left_bits = [179, 96, 63, 181, 115, 192, 159, 237, 20, 181, 18, 253, 164, 77, 199, 136]; + assert_eq!(&result.0[..], right_bits); + assert_eq!(&result.1[..], left_bits); + } +}