diff --git a/Cargo.toml b/Cargo.toml index 056bdaf..bb424f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,3 +38,7 @@ chunking = {path="chunking"} [build-dependencies] pkg-config = "0.3" + +[features] +default = [] +bench = [] diff --git a/src/cli/algotest.rs b/src/cli/algotest.rs index 06c2274..69c87b1 100644 --- a/src/cli/algotest.rs +++ b/src/cli/algotest.rs @@ -184,7 +184,7 @@ pub fn run(path: &str, bundle_size: usize, chunker: ChunkerType, compression: Op c.finish(&mut dummy).unwrap(); } }).num_milliseconds() as f32 / 1_000.0; - println!("- {}, {}", to_duration(decompress_time), to_speed(size, decompress_time)); + println!("- {}, {}", to_duration(decompress_time), to_speed(total_size - dup_size as u64, decompress_time)); total_read_time += decompress_time; } diff --git a/src/main.rs b/src/main.rs index bbef9fd..2ac0a83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ #![recursion_limit="128"] #![allow(unknown_lints, float_cmp)] +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] extern crate test; extern crate serde; extern crate serde_bytes; extern crate rmp_serde; diff --git a/src/util/compression.rs b/src/util/compression.rs index 1cca334..81eeaca 100644 --- a/src/util/compression.rs +++ b/src/util/compression.rs @@ -393,3 +393,455 @@ mod tests { } } + + +#[cfg(feature = "bench")] +mod benches { + + #[allow(unused_imports)] + use super::*; + + use test::Bencher; + + + #[allow(dead_code, needless_range_loop)] + fn test_data(n: usize) -> Vec { + let mut input = vec![0; n]; + for i in 0..input.len() { + input[i] = (i * i * i) as u8; + } + input + } + + #[allow(dead_code)] + fn bench_stream_compression(b: &mut Bencher, method: Compression) { + let input = test_data(512*1024); + b.iter(|| { + let mut compressor = method.compress_stream().unwrap(); + let mut compressed = Vec::with_capacity(input.len()); + compressor.process(&input, &mut compressed).unwrap(); + compressor.finish(&mut compressed).unwrap(); + }); + b.bytes = input.len() as u64; + } + + #[allow(dead_code)] + fn bench_stream_decompression(b: &mut Bencher, method: Compression) { + let input = test_data(512*1024); + let mut compressor = method.compress_stream().unwrap(); + let mut compressed = Vec::with_capacity(input.len()); + compressor.process(&input, &mut compressed).unwrap(); + compressor.finish(&mut compressed).unwrap(); + b.iter(|| { + let mut decompressor = method.decompress_stream().unwrap(); + let mut decompressed = Vec::with_capacity(compressed.len()); + decompressor.process(&compressed, &mut decompressed).unwrap(); + decompressor.finish(&mut decompressed).unwrap(); + }); + b.bytes = input.len() as u64; + } + + #[bench] + fn bench_deflate_1_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/1").unwrap()) + } + + #[bench] + fn bench_deflate_2_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/2").unwrap()) + } + + #[bench] + fn bench_deflate_3_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/3").unwrap()) + } + + #[bench] + fn bench_deflate_4_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/4").unwrap()) + } + + #[bench] + fn bench_deflate_5_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/5").unwrap()) + } + + #[bench] + fn bench_deflate_6_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/6").unwrap()) + } + + #[bench] + fn bench_deflate_7_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/7").unwrap()) + } + + #[bench] + fn bench_deflate_8_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/8").unwrap()) + } + + #[bench] + fn bench_deflate_9_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("deflate/9").unwrap()) + } + + #[bench] + fn bench_deflate_1_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/1").unwrap()) + } + + #[bench] + fn bench_deflate_2_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/2").unwrap()) + } + + #[bench] + fn bench_deflate_3_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/3").unwrap()) + } + + #[bench] + fn bench_deflate_4_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/4").unwrap()) + } + + #[bench] + fn bench_deflate_5_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/5").unwrap()) + } + + #[bench] + fn bench_deflate_6_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/6").unwrap()) + } + + #[bench] + fn bench_deflate_7_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/7").unwrap()) + } + + #[bench] + fn bench_deflate_8_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/8").unwrap()) + } + + #[bench] + fn bench_deflate_9_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("deflate/9").unwrap()) + } + + + #[bench] + fn bench_brotli_1_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/1").unwrap()) + } + + #[bench] + fn bench_brotli_2_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/2").unwrap()) + } + + #[bench] + fn bench_brotli_3_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/3").unwrap()) + } + + #[bench] + fn bench_brotli_4_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/4").unwrap()) + } + + #[bench] + fn bench_brotli_5_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/5").unwrap()) + } + + #[bench] + fn bench_brotli_6_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/6").unwrap()) + } + + #[bench] + fn bench_brotli_7_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/7").unwrap()) + } + + #[bench] + fn bench_brotli_8_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/8").unwrap()) + } + + #[bench] + fn bench_brotli_9_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/9").unwrap()) + } + + #[bench] + fn bench_brotli_10_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/10").unwrap()) + } + + #[bench] + fn bench_brotli_11_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("brotli/11").unwrap()) + } + + #[bench] + fn bench_brotli_1_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/1").unwrap()) + } + + #[bench] + fn bench_brotli_2_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/2").unwrap()) + } + + #[bench] + fn bench_brotli_3_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/3").unwrap()) + } + + #[bench] + fn bench_brotli_4_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/4").unwrap()) + } + + #[bench] + fn bench_brotli_5_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/5").unwrap()) + } + + #[bench] + fn bench_brotli_6_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/6").unwrap()) + } + + #[bench] + fn bench_brotli_7_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/7").unwrap()) + } + + #[bench] + fn bench_brotli_8_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/8").unwrap()) + } + + #[bench] + fn bench_brotli_9_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/9").unwrap()) + } + + #[bench] + fn bench_brotli_10_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/10").unwrap()) + } + + #[bench] + fn bench_brotli_11_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("brotli/11").unwrap()) + } + + + #[bench] + fn bench_lzma_1_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/1").unwrap()) + } + + #[bench] + fn bench_lzma_2_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/2").unwrap()) + } + + #[bench] + fn bench_lzma_3_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/3").unwrap()) + } + + #[bench] + fn bench_lzma_4_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/4").unwrap()) + } + + #[bench] + fn bench_lzma_5_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/5").unwrap()) + } + + #[bench] + fn bench_lzma_6_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/6").unwrap()) + } + + #[bench] + fn bench_lzma_7_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/7").unwrap()) + } + + #[bench] + fn bench_lzma_8_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/8").unwrap()) + } + + #[bench] + fn bench_lzma_9_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lzma/9").unwrap()) + } + + #[bench] + fn bench_lzma_1_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/1").unwrap()) + } + + #[bench] + fn bench_lzma_2_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/2").unwrap()) + } + + #[bench] + fn bench_lzma_3_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/3").unwrap()) + } + + #[bench] + fn bench_lzma_4_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/4").unwrap()) + } + + #[bench] + fn bench_lzma_5_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/5").unwrap()) + } + + #[bench] + fn bench_lzma_6_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/6").unwrap()) + } + + #[bench] + fn bench_lzma_7_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/7").unwrap()) + } + + #[bench] + fn bench_lzma_8_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/8").unwrap()) + } + + #[bench] + fn bench_lzma_9_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lzma/9").unwrap()) + } + + + #[bench] + fn bench_lz4_1_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/1").unwrap()) + } + + #[bench] + fn bench_lz4_2_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/2").unwrap()) + } + + #[bench] + fn bench_lz4_3_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/3").unwrap()) + } + + #[bench] + fn bench_lz4_4_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/4").unwrap()) + } + + #[bench] + fn bench_lz4_5_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/5").unwrap()) + } + + #[bench] + fn bench_lz4_6_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/6").unwrap()) + } + + #[bench] + fn bench_lz4_7_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/7").unwrap()) + } + + #[bench] + fn bench_lz4_8_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/8").unwrap()) + } + + #[bench] + fn bench_lz4_9_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/9").unwrap()) + } + + #[bench] + fn bench_lz4_10_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/10").unwrap()) + } + + #[bench] + fn bench_lz4_11_compress(b: &mut Bencher) { + bench_stream_compression(b, Compression::from_string("lz4/11").unwrap()) + } + + #[bench] + fn bench_lz4_1_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/1").unwrap()) + } + + #[bench] + fn bench_lz4_2_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/2").unwrap()) + } + + #[bench] + fn bench_lz4_3_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/3").unwrap()) + } + + #[bench] + fn bench_lz4_4_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/4").unwrap()) + } + + #[bench] + fn bench_lz4_5_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/5").unwrap()) + } + + #[bench] + fn bench_lz4_6_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/6").unwrap()) + } + + #[bench] + fn bench_lz4_7_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/7").unwrap()) + } + + #[bench] + fn bench_lz4_8_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/8").unwrap()) + } + + #[bench] + fn bench_lz4_9_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/9").unwrap()) + } + + #[bench] + fn bench_lz4_10_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/10").unwrap()) + } + + #[bench] + fn bench_lz4_11_decompress(b: &mut Bencher) { + bench_stream_decompression(b, Compression::from_string("lz4/11").unwrap()) + } + +} diff --git a/src/util/encryption.rs b/src/util/encryption.rs index 31499e1..2bc7e7b 100644 --- a/src/util/encryption.rs +++ b/src/util/encryption.rs @@ -85,7 +85,7 @@ impl EncryptionMethod { pub type Encryption = (EncryptionMethod, ByteBuf); -struct KeyfileYaml { +pub struct KeyfileYaml { public: String, secret: String } @@ -116,7 +116,7 @@ impl KeyfileYaml { pub struct Crypto { - path: PathBuf, + path: Option, keys: HashMap } @@ -124,7 +124,7 @@ impl Crypto { #[inline] pub fn dummy() -> Self { sodium_init(); - Crypto { path: PathBuf::new(), keys: HashMap::new() } + Crypto { path: None, keys: HashMap::new() } } pub fn open>(path: P) -> Result { @@ -140,7 +140,7 @@ impl Crypto { let secret = try!(SecretKey::from_slice(&secret).ok_or(EncryptionError::InvalidKey)); keys.insert(public, secret); } - Ok(Crypto { path: path, keys: keys }) + Ok(Crypto { path: Some(path), keys: keys }) } #[inline] @@ -154,8 +154,12 @@ impl Crypto { self.register_secret_key(public, secret) } + #[inline] pub fn load_keypair_from_file>(path: P) -> Result<(PublicKey, SecretKey), EncryptionError> { - let keyfile = try!(KeyfileYaml::load(path)); + Self::load_keypair_from_file_data(&try!(KeyfileYaml::load(path))) + } + + pub fn load_keypair_from_file_data(keyfile: &KeyfileYaml) -> Result<(PublicKey, SecretKey), EncryptionError> { let public = try!(parse_hex(&keyfile.public).map_err(|_| EncryptionError::InvalidKey)); let public = try!(PublicKey::from_slice(&public).ok_or(EncryptionError::InvalidKey)); let secret = try!(parse_hex(&keyfile.secret).map_err(|_| EncryptionError::InvalidKey)); @@ -163,15 +167,22 @@ impl Crypto { Ok((public, secret)) } + #[inline] + pub fn save_keypair_to_file_data(public: &PublicKey, secret: &SecretKey) -> KeyfileYaml { + KeyfileYaml { public: to_hex(&public[..]), secret: to_hex(&secret[..]) } + } + #[inline] pub fn save_keypair_to_file>(public: &PublicKey, secret: &SecretKey, path: P) -> Result<(), EncryptionError> { - KeyfileYaml { public: to_hex(&public[..]), secret: to_hex(&secret[..]) }.save(path) + Self::save_keypair_to_file_data(public, secret).save(path) } #[inline] pub fn register_secret_key(&mut self, public: PublicKey, secret: SecretKey) -> Result<(), EncryptionError> { - let path = self.path.join(to_hex(&public[..]) + ".yaml"); - try!(Self::save_keypair_to_file(&public, &secret, path)); + if let Some(ref path) = self.path { + let path = path.join(to_hex(&public[..]) + ".yaml"); + try!(Self::save_keypair_to_file(&public, &secret, path)); + } self.keys.insert(public, secret); Ok(()) } @@ -231,3 +242,153 @@ impl Crypto { (PublicKey::from_slice(&pk).unwrap(), SecretKey::from_slice(&sk).unwrap()) } } + + + +mod tests { + + #[allow(unused_imports)] + use super::*; + + + #[test] + fn test_gen_keypair() { + let key1 = Crypto::gen_keypair(); + let key2 = Crypto::gen_keypair(); + assert!(key1.0 != key2.0); + } + + #[test] + fn test_keypair_from_password() { + let key1 = Crypto::keypair_from_password("foo"); + let key2 = Crypto::keypair_from_password("foo"); + assert_eq!(key1.0, key2.0); + let key3 = Crypto::keypair_from_password("bar"); + assert!(key1.0 != key3.0); + } + + #[test] + fn test_add_keypair() { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + assert!(!crypto.contains_secret_key(&pk)); + crypto.add_secret_key(pk, sk); + assert!(crypto.contains_secret_key(&pk)); + } + + #[test] + fn test_save_load_keyfile() { + let (pk, sk) = Crypto::gen_keypair(); + let data = Crypto::save_keypair_to_file_data(&pk, &sk); + let res = Crypto::load_keypair_from_file_data(&data); + assert!(res.is_ok()); + let (pk2, sk2) = res.unwrap(); + assert_eq!(pk, pk2); + assert_eq!(sk, sk2); + } + + #[test] + fn test_encrypt_decrpyt() { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + crypto.add_secret_key(pk, sk); + let encryption = (EncryptionMethod::Sodium, ByteBuf::from(&pk[..])); + let cleartext = b"test123"; + let result = crypto.encrypt(&encryption, cleartext); + assert!(result.is_ok()); + let ciphertext = result.unwrap(); + assert!(&ciphertext != cleartext); + let result = crypto.decrypt(&encryption, &ciphertext); + assert!(result.is_ok()); + let unciphered = result.unwrap(); + assert_eq!(&cleartext[..] as &[u8], &unciphered as &[u8]); + } + + #[test] + fn test_wrong_key() { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + crypto.add_secret_key(pk, sk.clone()); + let encryption = (EncryptionMethod::Sodium, ByteBuf::from(&pk[..])); + let cleartext = b"test123"; + let result = crypto.encrypt(&encryption, cleartext); + assert!(result.is_ok()); + let ciphertext = result.unwrap(); + assert!(&ciphertext != cleartext); + let mut crypto2 = Crypto::dummy(); + let mut sk2 = sk[..].to_vec(); + sk2[4] ^= 53; + assert!(&sk[..] as &[u8] != &sk2[..] as &[u8]); + crypto2.add_secret_key(pk, SecretKey::from_slice(&sk2).unwrap()); + let result = crypto2.decrypt(&encryption, &ciphertext); + assert!(result.is_err()); + } + + #[test] + fn test_modified_ciphertext() { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + crypto.add_secret_key(pk, sk.clone()); + let encryption = (EncryptionMethod::Sodium, ByteBuf::from(&pk[..])); + let cleartext = b"test123"; + let result = crypto.encrypt(&encryption, cleartext); + assert!(result.is_ok()); + let mut ciphertext = result.unwrap(); + assert!(&ciphertext != cleartext); + ciphertext[4] ^= 53; + let result = crypto.decrypt(&encryption, &ciphertext); + assert!(result.is_err()); + + } + +} + + + +#[cfg(feature = "bench")] +mod benches { + + #[allow(unused_imports)] + use super::*; + + use test::Bencher; + + + #[allow(dead_code, needless_range_loop)] + fn test_data(n: usize) -> Vec { + let mut input = vec![0; n]; + for i in 0..input.len() { + input[i] = (i * i * i) as u8; + } + input + } + + #[bench] + fn bench_key_generate(b: &mut Bencher) { + b.iter(|| Crypto::gen_keypair()); + } + + #[bench] + fn bench_encrypt(b: &mut Bencher) { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + crypto.add_secret_key(pk, sk.clone()); + let encryption = (EncryptionMethod::Sodium, ByteBuf::from(&pk[..])); + let input = test_data(512*1024); + b.iter(|| crypto.encrypt(&encryption, &input)); + b.bytes = input.len() as u64; + } + + #[bench] + fn bench_decrypt(b: &mut Bencher) { + let mut crypto = Crypto::dummy(); + let (pk, sk) = Crypto::gen_keypair(); + crypto.add_secret_key(pk, sk.clone()); + let encryption = (EncryptionMethod::Sodium, ByteBuf::from(&pk[..])); + let input = test_data(512*1024); + let output = crypto.encrypt(&encryption, &input).unwrap(); + b.iter(|| crypto.decrypt(&encryption, &output)); + b.bytes = input.len() as u64; + } + +}