diff --git a/fixed-hash/Cargo.toml b/fixed-hash/Cargo.toml index c96ea559e..c85eb2417 100644 --- a/fixed-hash/Cargo.toml +++ b/fixed-hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.3.1" +version = "0.3.2" authors = ["Parity Technologies "] license = "MIT" homepage = "https://github.com/paritytech/parity-common" diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs index 83273bc87..7c2c96609 100644 --- a/fixed-hash/src/hash.rs +++ b/fixed-hash/src/hash.rs @@ -513,7 +513,7 @@ macro_rules! impl_rand_for_fixed_hash { /// Assign `self` to a cryptographically random value. pub fn randomize(&mut self) { - let mut rng = $crate::rand::OsRng::new().unwrap(); + let mut rng = $crate::rand::rngs::EntropyRng::new(); self.randomize_using(&mut rng); } diff --git a/kvdb-rocksdb/src/lib.rs b/kvdb-rocksdb/src/lib.rs index eceebbc43..717a860ee 100644 --- a/kvdb-rocksdb/src/lib.rs +++ b/kvdb-rocksdb/src/lib.rs @@ -59,6 +59,8 @@ fn other_io_err(e: E) -> io::Error where E: Into CompactionProfile { CompactionProfile { - initial_file_size: 64 * 1024 * 1024, - block_size: 16 * 1024, + initial_file_size: 64 * MB as u64, + block_size: 16 * KB, write_rate_limit: None, } } @@ -151,9 +153,9 @@ impl CompactionProfile { /// Slow HDD compaction profile pub fn hdd() -> CompactionProfile { CompactionProfile { - initial_file_size: 256 * 1024 * 1024, - block_size: 64 * 1024, - write_rate_limit: Some(16 * 1024 * 1024), + initial_file_size: 256 * MB as u64, + block_size: 64 * KB, + write_rate_limit: Some(16 * MB as u64), } } } @@ -181,7 +183,7 @@ impl DatabaseConfig { } pub fn memory_budget(&self) -> usize { - self.memory_budget.unwrap_or(DB_DEFAULT_MEMORY_BUDGET_MB) * 1024 * 1024 + self.memory_budget.unwrap_or(DB_DEFAULT_MEMORY_BUDGET_MB) * MB } pub fn memory_budget_per_col(&self) -> usize { @@ -303,7 +305,9 @@ impl Database { { block_opts.set_block_size(config.compaction.block_size); - let cache_size = cmp::max(8, config.memory_budget() / 3); + // Set cache size as recommended by + // https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning#block-cache-size + let cache_size = config.memory_budget() / 3; let cache = Cache::new(cache_size); block_opts.set_cache(cache); } diff --git a/parity-crypto/Cargo.toml b/parity-crypto/Cargo.toml index 3758f0f5c..f5d113290 100644 --- a/parity-crypto/Cargo.toml +++ b/parity-crypto/Cargo.toml @@ -1,13 +1,28 @@ [package] name = "parity-crypto" -version = "0.3.0" +version = "0.3.1" authors = ["Parity Technologies "] repository = "https://github.com/paritytech/parity-common" description = "Crypto utils used by ethstore and network." license = "GPL-3.0" +autobenches = false + +[[bench]] +name = "bench" +harness = false + [dependencies] quick-error = "1.2.2" -ring = "0.14.3" -rust-crypto = "0.2.36" tiny-keccak = "1.4" +scrypt = { version = "0.1.1", default-features = false } +ripemd160 = "0.8.0" +sha2 = "0.8.0" +digest = "0.8" +aes = "0.3.2" +aes-ctr = "0.3.0" +block-modes = "0.3.3" +ring = "0.14.6" + +[dev-dependencies] +criterion = "0.2" diff --git a/parity-crypto/benches/bench.rs b/parity-crypto/benches/bench.rs new file mode 100644 index 000000000..f9f68dfd1 --- /dev/null +++ b/parity-crypto/benches/bench.rs @@ -0,0 +1,56 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + + +extern crate parity_crypto; + +#[macro_use] +extern crate criterion; + +use criterion::{Criterion, Bencher}; + +criterion_group!(benches, input_len); + +criterion_main!(benches); + +/// general benches for multiple input size +fn input_len(c: &mut Criterion) { + + c.bench_function_over_inputs("ripemd", + |b: &mut Bencher, size: &usize| { + let data = vec![0u8; *size]; + b.iter(|| parity_crypto::digest::ripemd160(&data[..])); + }, + vec![100, 500, 1_000, 10_000, 100_000] + ); + + c.bench_function_over_inputs("aes_ctr", + |b: &mut Bencher, size: &usize| { + let data = vec![0u8; *size]; + let mut dest = vec![0; *size]; + let k = [0; 16]; + let iv = [0; 16]; + + b.iter(||{ + parity_crypto::aes::encrypt_128_ctr(&k[..], &iv[..], &data[..], &mut dest[..]).unwrap(); + // same as encrypt but add it just in case + parity_crypto::aes::decrypt_128_ctr(&k[..], &iv[..], &data[..], &mut dest[..]).unwrap(); + }); + }, + vec![100, 500, 1_000, 10_000, 100_000] + ); + +} diff --git a/parity-crypto/src/aes.rs b/parity-crypto/src/aes.rs index 42a26fad0..885032b69 100644 --- a/parity-crypto/src/aes.rs +++ b/parity-crypto/src/aes.rs @@ -14,40 +14,195 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use block_modes::{BlockMode}; +use block_modes::block_padding::Pkcs7; +use block_modes::block_padding::ZeroPadding; +use block_modes::{ Cbc, Ecb }; +use raes::{ Aes128, Aes256 }; +use aes_ctr::{ Aes128Ctr, Aes256Ctr }; +use aes_ctr::stream_cipher::{ NewStreamCipher, SyncStreamCipher }; use error::SymmError; -use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; -use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; -use rcrypto::symmetriccipher::{Encryptor, Decryptor}; -use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer, WriteBuffer}; +use raes::block_cipher_trait::generic_array::GenericArray; + + +/// One time encoder/decoder for Ecb mode Aes256 with zero padding +pub struct AesEcb256(Ecb); + +impl AesEcb256 { + + /// New encoder/decoder, no iv for ecb + pub fn new(key: &[u8]) -> Result { + Ok(AesEcb256(Ecb::new_var(key, &[])?)) + } + + /// Encrypt data in place without padding. The data length must be a multiple + /// of the block size. + pub fn encrypt(self, content: &mut [u8]) -> Result<(), SymmError> { + let len = content.len(); + self.0.encrypt(content, len)?; + Ok(()) + } + + /// Decrypt data in place without padding. The data length must be a multiple + /// of the block size. + pub fn decrypt(self, content: &mut [u8]) -> Result<(), SymmError> { + self.0.decrypt(content)?; + Ok(()) + } +} + + +/// Reusable encoder/decoder for Aes256 in Ctr mode and no padding +pub struct AesCtr256(Aes256Ctr); + +impl AesCtr256 { + + /// New encoder/decoder + pub fn new(key: &[u8], iv: &[u8]) -> Result { + Ok(AesCtr256( + Aes256Ctr::new(GenericArray::from_slice(key), GenericArray::from_slice(iv)) + )) + } + + /// In place encrypt a content without padding, the content length must be a multiple + /// of the block size. + pub fn encrypt(&mut self, content: &mut[u8]) -> Result<(), SymmError> { + self.0.try_apply_keystream(content)?; + Ok(()) + } + + /// In place decrypt a content without padding, the content length must be a multiple + /// of the block size. + pub fn decrypt(&mut self, content: &mut[u8]) -> Result<(), SymmError> { + self.0.try_apply_keystream(content)?; + Ok(()) + } +} /// Encrypt a message (CTR mode). /// /// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. /// An error is returned if the input lengths are invalid. +/// If possible prefer `inplace_encrypt_128_ctr` to avoid a slice copy. 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 encryptor = Aes128Ctr::new( + GenericArray::from_slice(k), + GenericArray::from_slice(iv), + ); + &mut dest[..plain.len()].copy_from_slice(plain); + encryptor.try_apply_keystream(dest)?; Ok(()) + +} + +/// Encrypt a message (CTR mode). +/// +/// 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 inplace_encrypt_128_ctr(k: &[u8], iv: &[u8], data: &mut [u8]) -> Result<(), SymmError> { + let mut encryptor = Aes128Ctr::new( + GenericArray::from_slice(k), + GenericArray::from_slice(iv), + ); + encryptor.try_apply_keystream(data)?; + Ok(()) + } /// Decrypt a message (CTR mode). /// /// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. /// An error is returned if the input lengths are invalid. +/// If possible prefer `inplace_decrypt_128_ctr` instead. 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 encryptor = Aes128Ctr::new( + GenericArray::from_slice(k), + GenericArray::from_slice(iv), + ); + + &mut dest[..encrypted.len()].copy_from_slice(encrypted); + encryptor.try_apply_keystream(dest)?; Ok(()) } +/// Decrypt a message (CTR mode). +/// +/// 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 inplace_decrypt_128_ctr(k: &[u8], iv: &[u8], data: &mut [u8]) -> Result<(), SymmError> { + let mut encryptor = Aes128Ctr::new( + GenericArray::from_slice(k), + GenericArray::from_slice(iv), + ); + + encryptor.try_apply_keystream(data)?; + Ok(()) +} + + /// Decrypt a message (CBC mode). /// /// 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_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result { - let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); - let len = dest.len(); - let mut buffer = RefWriteBuffer::new(dest); - encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut buffer, true)?; - Ok(len - buffer.remaining()) + let encryptor = Cbc::::new_var(k, iv)?; + &mut dest[..encrypted.len()].copy_from_slice(encrypted); + let unpad_length = { + encryptor.decrypt(&mut dest[..encrypted.len()])?.len() + }; + Ok(unpad_length) +} + + +#[cfg(test)] +mod tests { + + use super::*; + + // only use for test could be expose in the future + fn encrypt_128_cbc(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { + let encryptor = Cbc::::new_var(k, iv)?; + &mut dest[..plain.len()].copy_from_slice(plain); + encryptor.encrypt(dest, plain.len())?; + Ok(()) + } + + #[test] + pub fn test_aes_short() -> Result<(),SymmError> { + let key = [97, 110, 121, 99, 111, 110, 116, 101, 110, 116, 116, 111, 114, 101, 97, 99, 104, 49, 50, 56, 98, 105, 116, 115, 105, 122, 101, 10]; + let salt = [109, 121, 115, 97, 108, 116, 115, 104, 111, 117, 108, 100, 102, 105, 108, 108, 115, 111, 109, 109, 101, 98, 121, 116, 101, 108, 101, 110, 103, 116, 104, 10]; + let content = [83, 111, 109, 101, 32, 99, 111, 110, 116, 101, 110, 116, 32, 116, 111, 32, 116, 101, 115, 116, + 32, 97, 101, 115, 44, 10, 110, 111, 116, 32, 116, 111, 32, 109, 117, 99, 104, 32, 44, 32, 111, 110, 108, 121, + 32, 118, 101, 114, 121, 32, 98, 97, 115, 105, 99, 32, 116, 101, 115, 116, 32, 116, 111, 32, 97, 118, 111, 105, + 100, 32, 111, 98, 118, 105, 111, 117, 115, 32, 114, 101, 103, 114, 101, 115, 115, 105, 111, 110, 32, 119, 104, + 101, 110, 32, 115, 119, 105, 116, 99, 104, 105, 110, 103, 32, 108, 105, 98, 115, 46, 10]; + let ctr_enc = [65, 55, 246, 75, 24, 117, 30, 233, 218, 139, 91, 251, 251, 179, 171, 69, 60, 244, 249, 44, 238, 60, + 10, 66, 71, 10, 199, 111, 54, 24, 124, 223, 153, 250, 159, 154, 164, 109, 232, 82, 20, 199, 182, 40, 174, 104, 64, + 203, 236, 94, 222, 184, 117, 54, 234, 189, 253, 122, 135, 121, 100, 44, 227, 241, 123, 120, 110, 188, 109, 148, 112, + 160, 131, 205, 116, 104, 232, 8, 22, 170, 80, 231, 155, 246, 255, 115, 101, 5, 234, 104, 220, 199, 192, 166, 181, 156, + 113, 255, 187, 51, 38, 128, 75, 29, 237, 178, 205, 98, 101, 110]; + let cbc_enc = [167, 248, 5, 90, 11, 140, 215, 138, 165, 125, 137, 76, 47, 243, 191, 48, 183, 247, 109, 86, 24, 45, + 81, 215, 0, 51, 221, 185, 131, 97, 234, 189, 244, 255, 107, 210, 70, 60, 41, 221, 43, 137, 185, 166, 42, 65, 18, 200, + 151, 233, 255, 192, 109, 25, 105, 115, 161, 209, 126, 235, 99, 192, 241, 241, 19, 249, 87, 244, 28, 146, 186, 189, 108, + 9, 243, 132, 4, 105, 53, 162, 8, 235, 84, 107, 213, 59, 158, 113, 227, 120, 162, 50, 237, 123, 70, 187, 83, 73, 146, 13, + 44, 191, 53, 4, 125, 207, 176, 45, 8, 153, 175, 198]; + let mut dest = vec![0;110]; + let mut dest_padded = vec![0;112]; + let mut dest_padded2 = vec![0;128]; // TODO RustLib need an extra 16bytes in dest : looks extra buggy but function is not currently use (keep it private for now) + encrypt_128_cbc(&key[..16], &salt[..16], &content, &mut dest_padded2)?; + assert!(&dest_padded2[..112] == &cbc_enc[..]); + encrypt_128_ctr(&key[..16], &salt[..16], &content, &mut dest)?; + assert!(&dest[..] == &ctr_enc[..]); + let mut content_data = content.to_vec(); + inplace_encrypt_128_ctr(&key[..16], &salt[..16], &mut content_data[..])?; + assert!(&content_data[..] == &ctr_enc[..]); + decrypt_128_ctr(&key[..16], &salt[..16], &ctr_enc[..], &mut dest)?; + assert!(&dest[..] == &content[..]); + let mut content_data = ctr_enc.to_vec(); + inplace_decrypt_128_ctr(&key[..16], &salt[..16], &mut content_data[..])?; + assert!(&content_data[..] == &content[..]); + let l = decrypt_128_cbc(&key[..16], &salt[..16], &cbc_enc[..], &mut dest_padded)?; + assert!(&dest_padded[..l] == &content[..]); + Ok(()) + } } diff --git a/parity-crypto/src/digest.rs b/parity-crypto/src/digest.rs index b2be0b8ed..40bafe145 100644 --- a/parity-crypto/src/digest.rs +++ b/parity-crypto/src/digest.rs @@ -14,37 +14,46 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use rcrypto::ripemd160; -use ring::digest::{self, Context, SHA256, SHA512}; +use rripemd160; +use rsha2; use std::marker::PhantomData; use std::ops::Deref; +use rdigest::generic_array::GenericArray; +use rdigest::generic_array::typenum::{U20, U32, U64}; +use rsha2::Digest as RDigest; /// The message digest. pub struct Digest(InnerDigest, PhantomData); enum InnerDigest { - Ring(digest::Digest), - Ripemd160([u8; 20]), + Sha256(GenericArray), + Sha512(GenericArray), + Ripemd160(GenericArray), } impl Deref for Digest { type Target = [u8]; fn deref(&self) -> &Self::Target { match self.0 { - InnerDigest::Ring(ref d) => d.as_ref(), - InnerDigest::Ripemd160(ref d) => &d[..] + InnerDigest::Sha256(ref d) => &d[..], + InnerDigest::Sha512(ref d) => &d[..], + InnerDigest::Ripemd160(ref d) => &d[..], } } } /// Single-step sha256 digest computation. pub fn sha256(data: &[u8]) -> Digest { - Digest(InnerDigest::Ring(digest::digest(&SHA256, data)), PhantomData) + let mut hasher = Hasher::sha256(); + hasher.update(data); + hasher.finish() } /// Single-step sha512 digest computation. pub fn sha512(data: &[u8]) -> Digest { - Digest(InnerDigest::Ring(digest::digest(&SHA512, data)), PhantomData) + let mut hasher = Hasher::sha512(); + hasher.update(data); + hasher.finish() } /// Single-step ripemd160 digest computation. @@ -62,34 +71,39 @@ pub enum Ripemd160 {} pub struct Hasher(Inner, PhantomData); enum Inner { - Ring(Context), - Ripemd160(ripemd160::Ripemd160) + Sha256(rsha2::Sha256), + Sha512(rsha2::Sha512), + Ripemd160(rripemd160::Ripemd160) } impl Hasher { pub fn sha256() -> Hasher { - Hasher(Inner::Ring(Context::new(&SHA256)), PhantomData) + Hasher(Inner::Sha256(rsha2::Sha256::default()), PhantomData) } } impl Hasher { pub fn sha512() -> Hasher { - Hasher(Inner::Ring(Context::new(&SHA512)), PhantomData) + Hasher(Inner::Sha512(rsha2::Sha512::default()), PhantomData) } } impl Hasher { pub fn ripemd160() -> Hasher { - Hasher(Inner::Ripemd160(ripemd160::Ripemd160::new()), PhantomData) + Hasher(Inner::Ripemd160(rripemd160::Ripemd160::default()), PhantomData) } } impl Hasher { pub fn update(&mut self, data: &[u8]) { match self.0 { - Inner::Ring(ref mut ctx) => ctx.update(data), + Inner::Sha256(ref mut ctx) => { + ctx.input(data) + }, + Inner::Sha512(ref mut ctx) => { + ctx.input(data) + }, Inner::Ripemd160(ref mut ctx) => { - use rcrypto::digest::Digest; ctx.input(data) } } @@ -97,12 +111,14 @@ impl Hasher { pub fn finish(self) -> Digest { match self.0 { - Inner::Ring(ctx) => Digest(InnerDigest::Ring(ctx.finish()), PhantomData), - Inner::Ripemd160(mut ctx) => { - use rcrypto::digest::Digest; - let mut d = [0; 20]; - ctx.result(&mut d); - Digest(InnerDigest::Ripemd160(d), PhantomData) + Inner::Sha256(ctx) => { + Digest(InnerDigest::Sha256(ctx.result()), PhantomData) + }, + Inner::Sha512(ctx) => { + Digest(InnerDigest::Sha512(ctx.result()), PhantomData) + }, + Inner::Ripemd160(ctx) => { + Digest(InnerDigest::Ripemd160(ctx.result()), PhantomData) } } } diff --git a/parity-crypto/src/error.rs b/parity-crypto/src/error.rs index 4e5582e19..c64d172b2 100644 --- a/parity-crypto/src/error.rs +++ b/parity-crypto/src/error.rs @@ -14,8 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use rcrypto; use ring; +use rscrypt; +use block_modes; +use aes_ctr; +use std::error::Error as StdError; quick_error! { #[derive(Debug)] @@ -28,6 +31,19 @@ quick_error! { cause(e) from() } + AsymShort(det: &'static str) { + description(det) + } + AsymFull(e: Box) { + cause(&**e) + description(e.description()) + } + } +} + +impl Into for Error { + fn into(self) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::Other, format!("Crypto error: {}",self)) } } @@ -42,24 +58,43 @@ quick_error! { InvalidP { display("Invalid p argument of the scrypt encryption") } + ScryptParam(e: rscrypt::errors::InvalidParams) { + display("invalid params for scrypt: {}", e) + cause(e) + from() + } + ScryptLength(e: rscrypt::errors::InvalidOutputLen) { + display("invalid scrypt output length: {}", e) + cause(e) + from() + } } } + quick_error! { #[derive(Debug)] pub enum SymmError wraps PrivSymmErr { - RustCrypto(e: rcrypto::symmetriccipher::SymmetricCipherError) { + Offset(x: usize) { + display("offset {} greater than slice length", x) + } + BlockMode(e: block_modes::BlockModeError) { display("symmetric crypto error") from() } + KeyStream(e: aes_ctr::stream_cipher::LoopError) { + display("ctr key stream ended") + from() + } + InvalidKeyLength(e: block_modes::InvalidKeyIvLength) { + display("Error with RustCrypto key length : {}", e) + from() + } Ring(e: ring::error::Unspecified) { display("symmetric crypto error") cause(e) from() } - Offset(x: usize) { - display("offset {} greater than slice length", x) - } } } @@ -75,8 +110,20 @@ impl From for SymmError { } } -impl From for SymmError { - fn from(e: rcrypto::symmetriccipher::SymmetricCipherError) -> SymmError { - SymmError(PrivSymmErr::RustCrypto(e)) +impl From for SymmError { + fn from(e: block_modes::BlockModeError) -> SymmError { + SymmError(PrivSymmErr::BlockMode(e)) + } +} + +impl From for SymmError { + fn from(e: block_modes::InvalidKeyIvLength) -> SymmError { + SymmError(PrivSymmErr::InvalidKeyLength(e)) + } +} + +impl From for SymmError { + fn from(e: aes_ctr::stream_cipher::LoopError) -> SymmError { + SymmError(PrivSymmErr::KeyStream(e)) } } diff --git a/parity-crypto/src/hmac.rs b/parity-crypto/src/hmac/mod.rs similarity index 99% rename from parity-crypto/src/hmac.rs rename to parity-crypto/src/hmac/mod.rs index ff337ed02..1372fbe10 100644 --- a/parity-crypto/src/hmac.rs +++ b/parity-crypto/src/hmac/mod.rs @@ -86,3 +86,6 @@ impl VerifyKey { pub fn verify(k: &VerifyKey, data: &[u8], sig: &[u8]) -> bool { hmac::verify(&k.0, data, sig).is_ok() } + +#[cfg(test)] +mod test; diff --git a/parity-crypto/src/hmac/test.rs b/parity-crypto/src/hmac/test.rs new file mode 100644 index 000000000..a04e247e5 --- /dev/null +++ b/parity-crypto/src/hmac/test.rs @@ -0,0 +1,49 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + + +use super::*; +#[test] +fn simple_mac_and_verify() { + let input = b"Some bytes"; + let big_input = vec![7u8;2000]; + + let key1 = vec![3u8;64]; + let key2 = vec![4u8;128]; + + let sig_key1 = SigKey::sha256(&key1[..]); + let sig_key2 = SigKey::sha512(&key2[..]); + + let mut signer1 = Signer::with(&sig_key1); + let mut signer2 = Signer::with(&sig_key2); + + signer1.update(&input[..]); + for i in 0 .. big_input.len() / 33 { + signer2.update(&big_input[i*33..(i+1)*33]); + } + signer2.update(&big_input[(big_input.len() / 33)*33..]); + let sig1 = signer1.sign(); + assert_eq!(&sig1[..], [223, 208, 90, 69, 144, 95, 145, 180, 56, 155, 78, 40, 86, 238, 205, 81, 160, 245, 88, 145, 164, 67, 254, 180, 202, 107, 93, 249, 64, 196, 86, 225]); + let sig2 = signer2.sign(); + assert_eq!(&sig2[..], &[29, 63, 46, 122, 27, 5, 241, 38, 86, 197, 91, 79, 33, 107, 152, 195, 118, 221, 117, 119, 84, 114, 46, 65, 243, 157, 105, 12, 147, 176, 190, 37, 210, 164, 152, 8, 58, 243, 59, 206, 80, 10, 230, 197, 255, 110, 191, 180, 93, 22, 255, 0, 99, 79, 237, 229, 209, 199, 125, 83, 15, 179, 134, 89][..]); + assert_eq!(&sig1[..], &sign(&sig_key1, &input[..])[..]); + assert_eq!(&sig2[..], &sign(&sig_key2, &big_input[..])[..]); + let verif_key1 = VerifyKey::sha256(&key1[..]); + let verif_key2 = VerifyKey::sha512(&key2[..]); + assert!(verify(&verif_key1, &input[..], &sig1[..])); + assert!(verify(&verif_key2, &big_input[..], &sig2[..])); + +} diff --git a/parity-crypto/src/lib.rs b/parity-crypto/src/lib.rs index b80ba46b5..379e2619b 100644 --- a/parity-crypto/src/lib.rs +++ b/parity-crypto/src/lib.rs @@ -16,11 +16,17 @@ //! Crypto utils used by ethstore and network. -extern crate crypto as rcrypto; #[macro_use] extern crate quick_error; extern crate ring; extern crate tiny_keccak; +extern crate scrypt as rscrypt; +extern crate ripemd160 as rripemd160; +extern crate sha2 as rsha2; +extern crate digest as rdigest; +extern crate aes as raes; +extern crate aes_ctr; +extern crate block_modes; pub mod aes; pub mod aes_gcm; diff --git a/parity-crypto/src/pbkdf2.rs b/parity-crypto/src/pbkdf2/mod.rs similarity index 97% rename from parity-crypto/src/pbkdf2.rs rename to parity-crypto/src/pbkdf2/mod.rs index c4d5cca1c..693ef2182 100644 --- a/parity-crypto/src/pbkdf2.rs +++ b/parity-crypto/src/pbkdf2/mod.rs @@ -28,3 +28,7 @@ pub fn sha256(iter: NonZeroU32, salt: Salt, sec: Secret, out: &mut [u8; 32]) { pub fn sha512(iter: NonZeroU32, salt: Salt, sec: Secret, out: &mut [u8; 64]) { ring::pbkdf2::derive(&ring::digest::SHA512, iter, salt.0, sec.0, &mut out[..]) } + + +#[cfg(test)] +mod test; diff --git a/parity-crypto/src/pbkdf2/test.rs b/parity-crypto/src/pbkdf2/test.rs new file mode 100644 index 000000000..6fa594f25 --- /dev/null +++ b/parity-crypto/src/pbkdf2/test.rs @@ -0,0 +1,28 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use super::*; +use std::num::NonZeroU32; + +#[test] +fn basic_test() { + let mut dest = [0;32]; + let salt = [5;32]; + let secret = [7;32]; + sha256(NonZeroU32::new(3).expect("static input;qed"), Salt(&salt[..]), Secret(&secret[..]), &mut dest); + let res = [242, 33, 31, 124, 36, 223, 179, 185, 206, 175, 190, 253, 85, 33, 23, 126, 141, 29, 23, 97, 66, 63, 51, 196, 27, 255, 135, 206, 74, 137, 172, 87]; + assert_eq!(res, dest); +} diff --git a/parity-crypto/src/scrypt.rs b/parity-crypto/src/scrypt.rs index d47e55ed2..c5ba18833 100644 --- a/parity-crypto/src/scrypt.rs +++ b/parity-crypto/src/scrypt.rs @@ -15,8 +15,10 @@ // along with Parity. If not, see . use error::ScryptError; -use rcrypto::scrypt::{scrypt, ScryptParams}; use super::{KEY_LENGTH_AES, KEY_LENGTH}; +use rscrypt::{scrypt, ScryptParams}; +#[cfg(test)] +use std::io::Error; pub fn derive_key(pass: &[u8], salt: &[u8], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), ScryptError> { // sanity checks @@ -30,9 +32,31 @@ pub fn derive_key(pass: &[u8], salt: &[u8], n: u32, p: u32, r: u32) -> Result<(V } let mut derived_key = vec![0u8; KEY_LENGTH]; - let scrypt_params = ScryptParams::new(log_n, r, p); - scrypt(pass, salt, &scrypt_params, &mut derived_key); + let scrypt_params = ScryptParams::new(log_n, r, p)?; + scrypt(pass, 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())) } + + +// test is build from previous crypto lib behaviour, values may be incorrect +// if previous crypto lib got a bug. +#[test] +pub fn test_derive() -> Result<(),Error> { + let pass = [109, 121, 112, 97, 115, 115, 10]; + let salt = [109, 121, 115, 97, 108, 116, 115, 104, 111, 117, 108, 100, 102, 105, + 108, 108, 115, 111, 109, 109, 101, 98, 121, 116, 101, 108, 101, 110, 103, 116, 104, 10]; + let r1 = [93, 134, 79, 68, 223, 27, 44, 174, 236, 184, 179, 203, 74, 139, 73, 66]; + let r2 = [2, 24, 239, 131, 172, 164, 18, 171, 132, 207, 22, 217, 150, 20, 203, 37]; + let l1 = [6, 90, 119, 45, 67, 2, 99, 151, 81, 88, 166, 210, 244, 19, 123, 208]; + let l2 = [253, 123, 132, 12, 188, 89, 196, 2, 107, 224, 239, 231, 135, 177, 125, 62]; + + let (l,r) = derive_key(&pass[..],&salt, 262, 1, 8).unwrap(); + assert!(l == r1); + assert!(r == l1); + let (l,r) = derive_key(&pass[..],&salt, 144, 4, 4).unwrap(); + assert!(l == r2); + assert!(r == l2); + Ok(()) +} diff --git a/primitive-types/src/error.rs b/primitive-types/src/error.rs deleted file mode 100644 index 298fc14ed..000000000 --- a/primitive-types/src/error.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015-2019 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// TODO: Remove TryFrom and TryInto when Rust trait is stablized -// https://github.com/paritytech/parity-common/issues/103 -//! Error, `TryFrom` and `TryInto` trait, should be removed when standard library stablize those. - -/// Error type for conversion. -pub enum Error { - /// Overflow encountered. - Overflow, -} - -/// An attempted conversion that consumes `self`, which may or may not be -/// expensive. -/// -/// Library authors should not directly implement this trait, but should prefer -/// implementing the [`TryFrom`] trait, which offers greater flexibility and -/// provides an equivalent `TryInto` implementation for free, thanks to a -/// blanket implementation in the standard library. For more information on this, -/// see the documentation for [`Into`]. -/// -/// [`TryFrom`]: trait.TryFrom.html -/// [`Into`]: trait.Into.html -pub trait TryInto: Sized { - /// The type returned in the event of a conversion error. - type Error; - - /// Performs the conversion. - fn try_into(self) -> Result; -} - -/// Attempt to construct `Self` via a conversion. -pub trait TryFrom: Sized { - /// The type returned in the event of a conversion error. - type Error; - - /// Performs the conversion. - fn try_from(value: T) -> Result; -} - -// TryFrom implies TryInto -impl TryInto for T where U: TryFrom -{ - type Error = U::Error; - - fn try_into(self) -> Result { - U::try_from(self) - } -} - -pub enum Never { } - -// Infallible conversions are semantically equivalent to fallible conversions -// with an uninhabited error type. -impl TryFrom for T where T: From { - type Error = Never; - - fn try_from(value: U) -> Result { - Ok(T::from(value)) - } -} diff --git a/primitive-types/src/lib.rs b/primitive-types/src/lib.rs index 93e1061b0..d0e2e3cef 100644 --- a/primitive-types/src/lib.rs +++ b/primitive-types/src/lib.rs @@ -14,9 +14,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -mod error; - -pub use error::{Error, TryFrom, TryInto, Never}; +#[cfg(feature = "std")] +extern crate core; #[macro_use] extern crate uint; @@ -36,6 +35,14 @@ extern crate impl_codec; #[macro_use] extern crate impl_rlp; +use core::convert::TryFrom; + +/// Error type for conversion. +pub enum Error { + /// Overflow encountered. + Overflow, +} + construct_uint! { /// 128-bit unsigned integer. pub struct U128(2); diff --git a/uint/benches/bigint.rs b/uint/benches/bigint.rs index 2d08a4789..d759275fe 100644 --- a/uint/benches/bigint.rs +++ b/uint/benches/bigint.rs @@ -439,34 +439,36 @@ fn mulmod_u512_vs_biguint_vs_gmp(c: &mut Criterion) { ); } -fn bench_biguint_mulmod(b: &mut Bencher, z: U256) { +fn bench_biguint_mulmod(b: &mut Bencher, i: u64) { let x = - U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); + U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = - U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); + U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); + let z = U256::from(i); b.iter(|| { let w = to_biguint(x) * to_biguint(y); black_box(from_biguint(w % to_biguint(z))) }); } -fn bench_gmp_mulmod(b: &mut Bencher, z: U256) { +fn bench_gmp_mulmod(b: &mut Bencher, i: u64) { let x = - U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); + U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = - U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); + U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); + let z = U256::from(i); b.iter(|| { let w = to_gmp(x) * to_gmp(y); black_box(from_gmp(w % to_gmp(z))) }); } -fn bench_u512_mulmod(b: &mut Bencher, z: U256) { +fn bench_u512_mulmod(b: &mut Bencher, i: u64) { let x = - U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); + U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = - U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(); - let z = U512([z.0[0], z.0[1], z.0[2], z.0[3], 0, 0, 0, 0]); + U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); + let z = U512::from(i); b.iter(|| { let w = x.overflowing_mul(y).0; black_box(w % z)