diff --git a/.travis.yml b/.travis.yml index 753186e..b14a0d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,9 @@ matrix: - rust: nightly env: TEST_COMMAND=test FEATURES=--features="nightly" - rust: nightly - env: TEST_COMMAND=bench FEATURES=--features="bench" + env: TEST_COMMAND=bench FEATURES='' - rust: nightly - env: TEST_COMMAND=bench FEATURES=--features="nightly bench" + env: TEST_COMMAND=bench FEATURES=--features="nightly" script: - cargo $TEST_COMMAND $FEATURES diff --git a/Cargo.toml b/Cargo.toml index 06af84d..b22e552 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,12 +50,16 @@ default-features = false hex = "^0.3" sha2 = "^0.7" bincode = "^0.9" +criterion = "0.2" + +[[bench]] +name = "ed25519_benchmarks" +harness = false [features] default = ["std", "u64_backend"] # We don't add "rand/std" here because it would enable a bunch of Fuchsia dependencies. std = ["subtle/std", "curve25519-dalek/std"] -bench = [] nightly = ["curve25519-dalek/nightly", "subtle/nightly", "rand/nightly"] asm = ["sha2/asm"] yolocrypto = ["curve25519-dalek/yolocrypto"] diff --git a/benches/ed25519_benchmarks.rs b/benches/ed25519_benchmarks.rs new file mode 100644 index 0000000..b813b12 --- /dev/null +++ b/benches/ed25519_benchmarks.rs @@ -0,0 +1,114 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2018 Isis Lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - Isis Agora Lovecruft + +#[macro_use] +extern crate criterion; +extern crate ed25519_dalek; +extern crate rand; +extern crate sha2; + +use criterion::Criterion; + +mod helpers { + use rand::CryptoRng; + use rand::Error; + use rand::RngCore; + + /// A fake RNG which simply returns zeroes. + pub struct ZeroRng; + + impl ZeroRng { + pub fn new() -> ZeroRng { + ZeroRng + } + } + + impl RngCore for ZeroRng { + fn next_u32(&mut self) -> u32 { 0u32 } + + fn next_u64(&mut self) -> u64 { 0u64 } + + fn fill_bytes(&mut self, bytes: &mut [u8]) { + for i in 0 .. bytes.len() { + bytes[i] = 0; + } + } + + fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(bytes)) + } + } + + impl CryptoRng for ZeroRng { } +} + +mod ed25519_benches { + use super::*; + use super::helpers::ZeroRng; + use ed25519_dalek::ExpandedSecretKey; + use ed25519_dalek::Keypair; + use ed25519_dalek::Signature; + use rand::thread_rng; + use rand::ThreadRng; + use sha2::Sha512; + + fn sign(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: Keypair = Keypair::generate::(&mut csprng); + let msg: &[u8] = b""; + + c.bench_function("Ed25519 signing", move |b| { + b.iter(| | keypair.sign::(msg)) + }); + } + + fn sign_expanded_key(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: Keypair = Keypair::generate::(&mut csprng); + let expanded: ExpandedSecretKey = keypair.secret.expand::(); + let msg: &[u8] = b""; + + c.bench_function("Ed25519 signing with an expanded secret key", move |b| { + b.iter(| | expanded.sign::(msg, &keypair.public)) + }); + } + + fn verify(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: Keypair = Keypair::generate::(&mut csprng); + let msg: &[u8] = b""; + let sig: Signature = keypair.sign::(msg); + + c.bench_function("Ed25519 signature verification", move |b| { + b.iter(| | keypair.verify::(msg, &sig)) + }); + } + + fn key_generation(c: &mut Criterion) { + let mut rng: ZeroRng = ZeroRng::new(); + + c.bench_function("Ed25519 keypair generation", move |b| { + b.iter(| | Keypair::generate::(&mut rng)) + }); + } + + criterion_group!{ + name = ed25519_benches; + config = Criterion::default(); + targets = + sign, + sign_expanded_key, + verify, + key_generation, + } +} + +criterion_main!( + ed25519_benches::ed25519_benches, +); diff --git a/src/ed25519.rs b/src/ed25519.rs index fc79054..e4d5701 100644 --- a/src/ed25519.rs +++ b/src/ed25519.rs @@ -1129,90 +1129,3 @@ mod test { } } } - -#[cfg(all(test, feature = "bench"))] -mod bench { - use test::Bencher; - use rand::ChaChaRng; - use rand::Error; - use rand::RngCore; - use rand::SeedableRng; - use sha2::Sha512; - use super::*; - - /// A fake RNG which simply returns zeroes. - struct ZeroRng; - - impl ZeroRng { - pub fn new() -> ZeroRng { - ZeroRng - } - } - - impl RngCore for ZeroRng { - fn next_u32(&mut self) -> u32 { 0u32 } - - fn next_u64(&mut self) -> u64 { 0u64 } - - fn fill_bytes(&mut self, bytes: &mut [u8]) { - for i in 0 .. bytes.len() { - bytes[i] = 0; - } - } - - fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> { - Ok(self.fill_bytes(bytes)) - } - } - - impl CryptoRng for ZeroRng { } - - #[bench] - fn sign(b: &mut Bencher) { - let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]); - let keypair: Keypair = Keypair::generate::(&mut csprng); - let msg: &[u8] = b""; - - b.iter(| | keypair.sign::(msg)); - } - - #[bench] - fn sign_expanded_key(b: &mut Bencher) { - let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]); - let keypair: Keypair = Keypair::generate::(&mut csprng); - let expanded: ExpandedSecretKey = keypair.secret.expand::(); - let msg: &[u8] = b""; - - b.iter(| | expanded.sign::(msg, &keypair.public)); - } - - #[bench] - fn verify(b: &mut Bencher) { - let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]); - let keypair: Keypair = Keypair::generate::(&mut csprng); - let msg: &[u8] = b""; - let sig: Signature = keypair.sign::(msg); - - b.iter(| | keypair.verify::(msg, &sig)); - } - - #[bench] - fn key_generation(b: &mut Bencher) { - let mut rng: ZeroRng = ZeroRng::new(); - - b.iter(| | Keypair::generate::(&mut rng)); - } - - #[bench] - fn underlying_scalar_mult_basepoint(b: &mut Bencher) { - use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; - - let scalar: Scalar = Scalar::from_bits([ - 20, 130, 129, 196, 247, 182, 211, 102, - 11, 168, 169, 131, 159, 69, 126, 35, - 109, 193, 175, 54, 118, 234, 138, 81, - 60, 183, 80, 186, 92, 248, 132, 13, ]); - - b.iter(| | &scalar * &ED25519_BASEPOINT_TABLE); - } -}