Merge branch 'release/0.7.0'

This commit is contained in:
Isis Lovecruft 2018-07-15 23:24:51 +00:00
commit e6f224616d
Failed to extract signature
7 changed files with 701 additions and 369 deletions

View file

@ -7,23 +7,14 @@ rust:
env:
- TEST_COMMAND=test FEATURES=''
- TEST_COMMAND=test FEATURES=--features="serde"
matrix:
include:
- rust: stable
env: TEST_COMMAND=test FEATURES=--features="serde"
- rust: beta
env: TEST_COMMAND=test FEATURES=--features="serde"
- rust: nightly
env: TEST_COMMAND=test FEATURES=--features="serde"
- rust: nightly
env: TEST_COMMAND=build FEATURES=--no-default-features
env: TEST_COMMAND=build FEATURES="--no-default-features --features=u32_backend"
- rust: nightly
env: TEST_COMMAND=test FEATURES=--features="nightly"
- rust: nightly
env: TEST_COMMAND=bench FEATURES=--features="bench"
- rust: nightly
env: TEST_COMMAND=bench FEATURES=--features="nightly bench"
script:
- cargo $TEST_COMMAND $FEATURES

View file

@ -1,6 +1,6 @@
[package]
name = "ed25519-dalek"
version = "0.6.2"
version = "0.7.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>"]
readme = "README.md"
license = "BSD-3-Clause"
@ -16,16 +16,12 @@ exclude = [ ".gitignore", "TESTVECTORS", "res/*" ]
travis-ci = { repository = "dalek-cryptography/ed25519-dalek", branch = "master"}
[dependencies.curve25519-dalek]
version = "0.16"
default-features = false
[dependencies.subtle]
version = "0.6"
version = "0.18"
default-features = false
[dependencies.rand]
optional = true
version = "0.4"
version = "0.5"
default-features = false
[dependencies.digest]
version = "^0.7"
@ -50,11 +46,19 @@ default-features = false
hex = "^0.3"
sha2 = "^0.7"
bincode = "^0.9"
criterion = "0.2"
[[bench]]
name = "ed25519_benchmarks"
harness = false
[features]
default = ["std"]
std = ["rand", "subtle/std", "curve25519-dalek/std", "failure/std"]
bench = []
nightly = ["curve25519-dalek/nightly", "subtle/nightly"]
default = ["std", "u64_backend"]
# We don't add "rand/std" here because it would enable a bunch of Fuchsia dependencies.
std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly", "rand/nightly"]
asm = ["sha2/asm"]
yolocrypto = ["curve25519-dalek/yolocrypto"]
u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
avx2_backend = ["curve25519-dalek/avx2_backend"]

135
README.md
View file

@ -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/dalek-cryptography/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.
@ -14,64 +14,51 @@ reason for feature-gating the benchmarks is that Rust's `test::Bencher` is
unstable, and thus only works on the nightly channel. (We'd like people to be
able to compile and test on the stable and beta channels too!)
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:
On an Intel i9-7900X running at 3.30 GHz, without TurboBoost, 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Ⓐmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo 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_benchmarks-721332beed423bce
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: 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)
Ed25519 signing time: [15.617 us 15.630 us 15.647 us]
Ed25519 signature verification time: [45.930 us 45.968 us 46.011 us]
Ed25519 keypair generation time: [15.440 us 15.465 us 15.492 us]
test result: ok. 0 passed; 0 failed; 3 ignored; 3 measured
By enabling the avx2 backend (on machines with compatible microarchitectures),
the performance for signature verification is greatly improved:
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS="-C target_cpu=native"
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --no-default-features --features "std avx2_backend"
Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek)
Finished release [optimized] target(s) in 4.28s
Running target/release/deps/ed25519_benchmarks-e4866664de39c84d
Ed25519 signing time: [15.923 us 15.945 us 15.967 us]
Ed25519 signature verification time: [33.382 us 33.411 us 33.445 us]
Ed25519 keypair generation time: [15.246 us 15.260 us 15.275 us]
In comparison, the equivalent package in Golang performs as follows:
∃!isisⒶwintermute:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
PASS
BenchmarkKeyGeneration 20000 85880 ns/op
BenchmarkSigning 20000 89115 ns/op
BenchmarkVerification 10000 212585 ns/op
ok github.com/agl/ed25519 7.500s
BenchmarkKeyGeneration 30000 47007 ns/op
BenchmarkSigning 30000 48820 ns/op
BenchmarkVerification 10000 119701 ns/op
ok github.com/agl/ed25519 5.775s
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 and signing a rough average of 2x faster, and
verification 2.5-3x faster depending on the availability of avx2. 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:
Translating to a rough cycle count: we multiply by a factor of 3.3 to convert
nanoseconds to cycles per second on a 3300 Mhz CPU, that's 110256 cycles for
verification and 52618 for signing, which is competitive with hand-optimised
assembly implementations.
∃!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).
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
@ -82,7 +69,7 @@ valuable than simply cycle counts alone.
# Warnings
ed25519-dalek and
[our elliptic curve library](https://github.com/isislovecruft/curve25519-dalek)
[our elliptic curve library](https://github.com/dalek-cryptography/curve25519-dalek)
(which this code uses) have received *one* formal cryptographic and security
review. Neither have yet received what we would consider *sufficient* peer
review by other qualified cryptographers to be considered in any way, shape,
@ -96,7 +83,7 @@ or form, safe.
The signatures produced by this library are malleable, as discussed in
[the original paper](https://ed25519.cr.yp.to/ed25519-20110926.pdf):
![](https://github.com/isislovecruft/ed25519-dalek/blob/develop/res/ed25519-malleability.png)
![](https://github.com/dalek-cryptography/ed25519-dalek/blob/master/res/ed25519-malleability.png)
We could eliminate the malleability property by multiplying by the curve
cofactor, however, this would cause our implementation to *not* match the
@ -111,49 +98,67 @@ In short, if malleable signatures are bad for your protocol, don't use them.
Consider using a curve25519-based Verifiable Random Function (VRF), such as
[Trevor Perrin's VXEdDSA](https://www.whispersystems.org/docs/specifications/xeddsa/),
instead. We
[plan](https://github.com/isislovecruft/curve25519-dalek/issues/9) to
[plan](https://github.com/dalek-cryptography/curve25519-dalek/issues/9) to
eventually support VXEdDSA in curve25519-dalek.
# Installation
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).

View file

@ -0,0 +1,80 @@
// -*- mode: rust; -*-
//
// This file is part of ed25519-dalek.
// Copyright (c) 2018 Isis Lovecruft
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
#[macro_use]
extern crate criterion;
extern crate ed25519_dalek;
extern crate rand;
extern crate sha2;
use criterion::Criterion;
mod ed25519_benches {
use super::*;
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::<Sha512, _>(&mut csprng);
let msg: &[u8] = b"";
c.bench_function("Ed25519 signing", move |b| {
b.iter(| | keypair.sign::<Sha512>(msg))
});
}
fn sign_expanded_key(c: &mut Criterion) {
let mut csprng: ThreadRng = thread_rng();
let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
let expanded: ExpandedSecretKey = keypair.secret.expand::<Sha512>();
let msg: &[u8] = b"";
c.bench_function("Ed25519 signing with an expanded secret key", move |b| {
b.iter(| | expanded.sign::<Sha512>(msg, &keypair.public))
});
}
fn verify(c: &mut Criterion) {
let mut csprng: ThreadRng = thread_rng();
let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
let msg: &[u8] = b"";
let sig: Signature = keypair.sign::<Sha512>(msg);
c.bench_function("Ed25519 signature verification", move |b| {
b.iter(| | keypair.verify::<Sha512>(msg, &sig))
});
}
fn key_generation(c: &mut Criterion) {
let mut csprng: ThreadRng = thread_rng();
c.bench_function("Ed25519 keypair generation", move |b| {
b.iter(| | Keypair::generate::<Sha512, _>(&mut csprng))
});
}
criterion_group!{
name = ed25519_benches;
config = Criterion::default();
targets =
sign,
sign_expanded_key,
verify,
key_generation,
}
}
criterion_main!(
ed25519_benches::ed25519_benches,
);

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,6 @@ use core::fmt::Display;
/// need to pay any attention to these.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub (crate) enum InternalError {
#[allow(dead_code)]
PointDecompressionError,
ScalarFormatError,
/// An error in the length of bytes handed to a constructor.
@ -29,55 +28,52 @@ pub (crate) enum InternalError {
/// returning the error, and the `length` in bytes which its constructor
/// expects.
BytesLengthError{ name: &'static str, length: usize },
/// The verification equation wasn't satisfied
VerifyError,
}
impl Display for InternalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InternalError::PointDecompressionError
=> write!(f, "Cannot decompress extended twisted edwards point"),
=> write!(f, "Cannot decompress Edwards point"),
InternalError::ScalarFormatError
=> write!(f, "Cannot use scalar with high-bit set"),
InternalError::BytesLengthError{ name: n, length: l}
=> write!(f, "{} must be {} bytes in length", n, l),
InternalError::VerifyError
=> write!(f, "Verification equation was not satisfied"),
}
}
}
impl ::failure::Fail for InternalError {}
/// Errors which may occur in the `from_bytes()` constructors of `PublicKey`,
/// `SecretKey`, `ExpandedSecretKey`, `Keypair`, and `Signature`.
///
/// There was an internal problem due to parsing the `Signature`.
/// Errors which may occur while processing signatures and keypairs.
///
/// This error may arise due to:
///
/// * Being given bytes with a length different to what was expected.
///
/// * A problem decompressing `r`, a curve point, in the `Signature`, or the
/// curve point for a `PublicKey`.
///
/// * A problem with the format of `s`, a scalar, in the `Signature`. This
/// is only raised if the high-bit of the scalar was set. (Scalars must
/// only be constructed from 255-bit integers.)
/// * Being given bytes with a length different to what was expected.
///
/// * Failure of a signature to satisfy the verification equation.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub struct DecodingError(pub (crate) InternalError);
pub struct SignatureError(pub (crate) InternalError);
impl Display for DecodingError {
impl Display for SignatureError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
InternalError::PointDecompressionError => write!(f, "{}", self.0),
InternalError::ScalarFormatError => write!(f, "{}", self.0),
InternalError::BytesLengthError{ name: _, length: _ } => write!(f, "{}", self.0),
}
write!(f, "{}", self.0)
}
}
impl ::failure::Fail for DecodingError {
impl ::failure::Fail for SignatureError {
fn cause(&self) -> Option<&::failure::Fail> {
match self.0 {
InternalError::PointDecompressionError => Some(&self.0),
InternalError::ScalarFormatError => Some(&self.0),
InternalError::BytesLengthError{ name: _, length: _} => Some(&self.0),
}
Some(&self.0)
}
}

View file

@ -15,7 +15,7 @@
//!
//! First, we need to generate a `Keypair`, which includes both public and
//! secret halves of an asymmetric key. To do so, we need a cryptographically
//! secure pseudorandom number generator (CSPRING), and a hash function which
//! secure pseudorandom number generator (CSPRNG), and a hash function which
//! has 512 bits of output. For this example, we'll use the operating
//! system's builtin PRNG and SHA-512 to generate a keypair:
//!
@ -24,6 +24,7 @@
//! extern crate sha2;
//! extern crate ed25519_dalek;
//!
//! # #[cfg(all(feature = "std", feature = "sha2"))]
//! # fn main() {
//! use rand::Rng;
//! use rand::OsRng;
@ -31,9 +32,12 @@
//! use ed25519_dalek::Keypair;
//! use ed25519_dalek::Signature;
//!
//! let mut cspring: OsRng = OsRng::new().unwrap();
//! let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! let mut csprng: OsRng = OsRng::new().unwrap();
//! let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # }
//! #
//! # #[cfg(any(not(feature = "std"), not(feature = "sha2")))]
//! # fn main() { }
//! ```
//!
//! We can now use this `keypair` to sign a message:
@ -44,12 +48,13 @@
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # use rand::ChaChaRng;
//! # use rand::SeedableRng;
//! # use sha2::Sha512;
//! # use ed25519_dalek::Keypair;
//! # use ed25519_dalek::Signature;
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! let signature: Signature = keypair.sign::<Sha512>(message);
//! # }
@ -64,17 +69,16 @@
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # use rand::ChaChaRng;
//! # use rand::SeedableRng;
//! # use sha2::Sha512;
//! # use ed25519_dalek::Keypair;
//! # use ed25519_dalek::Signature;
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature: Signature = keypair.sign::<Sha512>(message);
//! let verified: bool = keypair.verify::<Sha512>(message, &signature);
//!
//! assert!(verified);
//! assert!(keypair.verify::<Sha512>(message, &signature).is_ok());
//! # }
//! ```
//!
@ -87,20 +91,19 @@
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # use rand::ChaChaRng;
//! # use rand::SeedableRng;
//! # use sha2::Sha512;
//! # use ed25519_dalek::Keypair;
//! # use ed25519_dalek::Signature;
//! use ed25519_dalek::PublicKey;
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature: Signature = keypair.sign::<Sha512>(message);
//!
//! let public_key: PublicKey = keypair.public;
//! let verified: bool = public_key.verify::<Sha512>(message, &signature);
//!
//! assert!(verified);
//! assert!(public_key.verify::<Sha512>(message, &signature).is_ok());
//! # }
//! ```
//!
@ -117,16 +120,15 @@
//! # extern crate sha2;
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::{Rng, OsRng};
//! # use rand::{Rng, ChaChaRng, SeedableRng};
//! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
//! use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature: Signature = keypair.sign::<Sha512>(message);
//! # let public_key: PublicKey = keypair.public;
//! # let verified: bool = public_key.verify::<Sha512>(message, &signature);
//!
//! let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.to_bytes();
//! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes();
@ -141,13 +143,13 @@
//! # extern crate rand;
//! # extern crate sha2;
//! # extern crate ed25519_dalek;
//! # use rand::{Rng, OsRng};
//! # use rand::{Rng, ChaChaRng, SeedableRng};
//! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, DecodingError};
//! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, SignatureError};
//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), DecodingError> {
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair_orig: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), SignatureError> {
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair_orig: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature_orig: Signature = keypair_orig.sign::<Sha512>(message);
//! # let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = keypair_orig.public.to_bytes();
@ -173,7 +175,7 @@
//! types additionally come with built-in [serde](https://serde.rs) support by
//! building `ed25519-dalek` via:
//!
//! ```ignore,bash
//! ```bash
//! $ cargo build --features="serde"
//! ```
//!
@ -191,12 +193,12 @@
//!
//! # #[cfg(feature = "serde")]
//! # fn main() {
//! # use rand::{Rng, OsRng};
//! # use rand::{Rng, ChaChaRng, SeedableRng};
//! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
//! use bincode::{serialize, Infinite};
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut csprng);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature: Signature = keypair.sign::<Sha512>(message);
//! # let public_key: PublicKey = keypair.public;
@ -223,14 +225,14 @@
//! #
//! # #[cfg(feature = "serde")]
//! # fn main() {
//! # use rand::{Rng, OsRng};
//! # use rand::{Rng, ChaChaRng, SeedableRng};
//! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
//! # use bincode::{serialize, Infinite};
//! use bincode::{deserialize};
//!
//! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair: Keypair = Keypair::generate::<Sha512>(&mut csprng);
//! let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! # let signature: Signature = keypair.sign::<Sha512>(message);
//! # let public_key: PublicKey = keypair.public;
@ -260,10 +262,7 @@
extern crate curve25519_dalek;
extern crate generic_array;
extern crate digest;
extern crate subtle;
extern crate failure;
#[cfg(feature = "std")]
extern crate rand;
#[cfg(any(feature = "std", test))]