Skip to content

Commit

Permalink
Merge branch 'master' into ao-then-get-ready-for-the-fast-div
Browse files Browse the repository at this point in the history
* master:
  uint: faster mul by u64 (#125)
  fix rocksdb block cache size (#122)
  uint: convert benchmarks to criterion  (#123)
  Bump fixed-hash to 0.3.2 (#134)
  Use EntropyRng instead of OsRng (#130)
  Bump parity-crypto to 0.3.1 (#132)
  rust-crypto dependency removal (#85)
  Use newly stablized TryFrom trait for primitive-types (#127)
  • Loading branch information
ordian committed May 7, 2019
2 parents 254ccd0 + a1ea210 commit c160588
Show file tree
Hide file tree
Showing 17 changed files with 487 additions and 138 deletions.
2 changes: 1 addition & 1 deletion fixed-hash/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "fixed-hash"
version = "0.3.1"
version = "0.3.2"
authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT"
homepage = "https://github.com/paritytech/parity-common"
Expand Down
2 changes: 1 addition & 1 deletion fixed-hash/src/hash.rs
Expand Up @@ -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);
}

Expand Down
18 changes: 11 additions & 7 deletions kvdb-rocksdb/src/lib.rs
Expand Up @@ -59,6 +59,8 @@ fn other_io_err<E>(e: E) -> io::Error where E: Into<Box<error::Error + Send + Sy
io::Error::new(io::ErrorKind::Other, e)
}

const KB: usize = 1024;
const MB: usize = 1024 * KB;
const DB_DEFAULT_MEMORY_BUDGET_MB: usize = 128;

enum KeyState {
Expand Down Expand Up @@ -142,18 +144,18 @@ impl CompactionProfile {
/// Default profile suitable for SSD storage
pub fn ssd() -> 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,
}
}

/// 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),
}
}
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
Expand Down
21 changes: 18 additions & 3 deletions parity-crypto/Cargo.toml
@@ -1,13 +1,28 @@
[package]
name = "parity-crypto"
version = "0.3.0"
version = "0.3.1"
authors = ["Parity Technologies <admin@parity.io>"]
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"
56 changes: 56 additions & 0 deletions 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 <http://www.gnu.org/licenses/>.


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]
);

}
181 changes: 168 additions & 13 deletions parity-crypto/src/aes.rs
Expand Up @@ -14,40 +14,195 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

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<Aes256, ZeroPadding>);

impl AesEcb256 {

/// New encoder/decoder, no iv for ecb
pub fn new(key: &[u8]) -> Result<Self, SymmError> {
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<Self, SymmError> {
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<usize, SymmError> {
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::<Aes128, Pkcs7>::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::<Aes128, Pkcs7>::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(())
}
}

0 comments on commit c160588

Please sign in to comment.