diff --git a/README.md b/README.md index 869b755..ce3ce08 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ed25519-dalek [![](https://img.shields.io/crates/v/ed25519-dalek.svg)](https://crates.io/crates/ed25519-dalek) [![](https://docs.rs/ed25519-dalek/badge.svg)](https://docs.rs/ed25519-dalek) [![](https://travis-ci.org/isislovecruft/ed25519-dalek.svg?branch=master)](https://travis-ci.org/isislovecruft/ed25519-dalek?branch=master) +# ed25519-dalek [![](https://img.shields.io/crates/v/ed25519-dalek.svg)](https://crates.io/crates/ed25519-dalek) [![](https://docs.rs/ed25519-dalek/badge.svg)](https://docs.rs/ed25519-dalek) [![](https://travis-ci.org/isislovecruft/ed25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/ed25519-dalek?branch=master) Fast and efficient Rust implementation of ed25519 key generation, signing, and verification in Rust. @@ -18,19 +18,23 @@ On an Intel i5 Sandy Bridge running at 2.6 GHz, with TurboBoost enabled (and also running in QubesOS with *lots* of other VMs executing), this code achieves the following performance benchmarks: - ∃!isisⒶwintermute:(develop *$)~/code/rust/ed25519 ∴ cargo bench --features="bench" - Finished release [optimized] target(s) in 0.0 secs - Running target/release/deps/ed25519_dalek-281c2d7a2379edae + ∃!isisⒶwintermute:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features="nightly bench" + Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek) + Finished release [optimized] target(s) in 3.11s + Running target/release/deps/ed25519_dalek-ae92163eefd0cc80 - running 6 tests + running 9 tests test ed25519::test::golden ... ignored + test ed25519::test::public_key_from_bytes ... ignored test ed25519::test::sign_verify ... ignored test ed25519::test::unmarshal_marshal ... ignored - test ed25519::bench::key_generation ... bench: 54,571 ns/iter (+/- 7,861) - test ed25519::bench::sign ... bench: 70,009 ns/iter (+/- 22,812) - test ed25519::bench::verify ... bench: 185,619 ns/iter (+/- 24,117) + test ed25519::bench::key_generation ... bench: 30,711 ns/iter (+/- 10,936) + test ed25519::bench::sign ... bench: 39,432 ns/iter (+/- 21,387) + test ed25519::bench::sign_expanded_key ... bench: 45,753 ns/iter (+/- 25,261) + test ed25519::bench::underlying_scalar_mult_basepoint ... bench: 25,455 ns/iter (+/- 10,587) + test ed25519::bench::verify ... bench: 91,408 ns/iter (+/- 31,193) - test result: ok. 0 passed; 0 failed; 3 ignored; 3 measured + test result: ok. 0 passed; 0 failed; 4 ignored; 5 measured; 0 filtered out In comparison, the equivalent package in Golang performs as follows: @@ -41,37 +45,22 @@ In comparison, the equivalent package in Golang performs as follows: BenchmarkVerification 10000 212585 ns/op ok github.com/agl/ed25519 7.500s -Making key generation, signing, and verification a rough average of one third -faster, one fifth faster, and one eighth faster respectively. Of course, this +Making key generation, signing, and verification a rough average of 33% +faster, 44% faster, and 43% faster respectively. Of course, this is just my machine, and these results—nowhere near rigorous—should be taken with a handful of salt. -Additionally, if you're on the Rust nightly channel, be sure to build with -`cargo build --features="nightly"`, which uses Rust's experimental support for -the `u128` type in curve25519-dalek to speed up field arithmetic by roughly a -factor of two. The benchmarks using nightly (on the same machine as above) -are: - - ∃!isisⒶwintermute:(develop *$)~/code/rust/ed25519 ∴ cargo bench --features="bench nightly" - Finished release [optimized] target(s) in 0.0 secs - Running target/release/deps/ed25519_dalek-9d7f8674ae11ac39 - - running 6 tests - test ed25519::test::golden ... ignored - test ed25519::test::sign_verify ... ignored - test ed25519::test::unmarshal_marshal ... ignored - test ed25519::bench::key_generation ... bench: 31,160 ns/iter (+/- 8,597) - test ed25519::bench::sign ... bench: 40,565 ns/iter (+/- 4,758) - test ed25519::bench::verify ... bench: 106,146 ns/iter (+/- 2,796) - - test result: ok. 0 passed; 0 failed; 3 ignored; 3 measured - Translating to a rough cycle count: we multiply by a factor of 2.6 to convert -nanoseconds to cycles per second on a 2.6 GHz CPU, that's 275979 cycles for -verification and 105469 for signing, which is -[competitive with the optimised assembly version](https://ed25519.cr.yp.to/) -included in the SUPERCOP benchmarking suite (albeit their numbers are for the -older Nehalem microarchitecture). +nanoseconds to cycles per second on a 2591 Mhz CPU, that's 237660 cycles for +verification and 102523 for signing, which for signing is competitive +with optimised assembly versions. + +Additionally, if you're on the Rust nightly channel, be sure to build with +`cargo build --features="nightly"` which enables more secure compiler +optimisation protections in the +[subtle](https://github.com/dalek-cryptography/subtle) crate. Additionally, if +you're using a CSPRNG from the `rand` crate, the `nightly` feature will enable +`u128`/`i128` features there, resulting in potentially faster performance. Additionally, thanks to Rust, this implementation has both type and memory safety. It's also easily readable by a much larger set of people than those who @@ -118,42 +107,60 @@ eventually support VXEdDSA in curve25519-dalek. To install, add the following to your project's `Cargo.toml`: - [dependencies.ed25519-dalek] - version = "^0.6" +```toml +[dependencies.ed25519-dalek] +version = "^0.7" +``` Then, in your library or executable source, add: - extern crate ed25519_dalek +```rust +extern crate ed25519_dalek; +``` + +# Features To cause your application to build `ed25519-dalek` with the nightly feature enabled by default, instead do: - [dependencies.ed25519-dalek] - version = "^0.6" - features = ["nightly"] +```toml +[dependencies.ed25519-dalek] +version = "^0.7" +features = ["nightly"] +``` To cause your application to instead build with the nightly feature enabled when someone builds with `cargo build --features="nightly"` add the following to the `Cargo.toml`: - [features] - nightly = ["ed25519-dalek/nightly"] - -Using the `nightly` feature will nearly double the latency of signing and -verification. +```toml +[features] +nightly = ["ed25519-dalek/nightly"] +``` To enable [serde](https://serde.rs) support, build `ed25519-dalek` with: - [dependencies.ed25519-dalek] - version = "^0.6" - features = ["serde"] +```toml +[dependencies.ed25519-dalek] +version = "^0.7" +features = ["serde"] +``` +By default, `ed25519-dalek` builds against `curve25519-dalek`'s `u64_backend` +feature, which uses Rust's `i128` feature to achieve roughly double the speed as +the `u32_backend` feature. When targetting 32-bit systems, however, you'll +likely want to compile with + `cargo build --no-default-features --features="u32_backend"`. +If you're building for a machine with avx2 instructions, there's also the +experimental `avx2_backend`. To use it, compile with +`RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features --features="avx2_backend"` # TODO + * Batch signature verification, maybe? * We can probably make this go even faster if we implement SHA512, rather than using the rust-crypto implementation whose API requires - that we allocate memory and memzero it before mutating to store the + that we allocate memory and bzero it before mutating to store the digest. * Incorporate ed25519-dalek into Brian Smith's [crypto-bench](https://github.com/briansmith/crypto-bench).