Merge branch 'release/0.3.0'

This commit is contained in:
Isis Lovecruft 2017-03-15 23:20:42 +00:00
commit b8df6454a3
Failed to extract signature
6 changed files with 328 additions and 116 deletions

23
.travis.yml Normal file
View file

@ -0,0 +1,23 @@
language: rust
rust:
- stable
- beta
- nightly
env:
- TEST_COMMAND=test FEATURES=''
matrix:
include:
- rust: nightly
env: TEST_COMMAND=build FEATURES='--no-default-features'
- 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.2.3"
version = "0.3.0"
authors = ["Isis Lovecruft <isis@torproject.org>"]
readme = "README.md"
license = "CC0-1.0"
@ -10,11 +10,13 @@ documentation = "https://docs.rs/ed25519-dalek"
keywords = ["cryptography", "ed25519", "curve25519", "signature", "ECC"]
categories = ["cryptography", "no-std"]
description = "Fast and efficient ed25519 signing and verification in pure Rust."
exclude = [ ".gitignore", "TESTVECTORS" ]
exclude = [ ".gitignore", "TESTVECTORS", "res/*" ]
[badges]
travis-ci = { repository = "isislovecruft/ed25519-dalek", branch = "master"}
[dependencies]
arrayref = "0.3.3"
sha2 = "^0.4"
[dependencies.curve25519-dalek]
version = "^0.6"
@ -24,9 +26,19 @@ default-features = false
optional = true
version = "^0.3"
[dependencies.digest]
version = "0.4"
[dependencies.generic-array]
# same version that digest depends on
version = "^0.6"
[dev-dependencies]
rustc-serialize = "0.3"
sha2 = "^0.4"
[features]
default = ["std"]
std = ["rand"]
std = ["rand", "curve25519-dalek/std"]
bench = []
nightly = ["curve25519-dalek/nightly"]

134
README.md
View file

@ -1,28 +1,38 @@
# ed25519-dalek ![](https://img.shields.io/crates/v/ed25519-dalek.svg) ![](https://docs.rs/ed25519-dalek/badge.svg)
# ed25519-dalek ![](https://img.shields.io/crates/v/ed25519-dalek.svg) ![](https://docs.rs/ed25519-dalek/badge.svg) ![](https://travis-ci.org/isislovecruft/ed25519-dalek.svg?branch=master)
Fast and efficient Rust implementation of ed25519 key generation, signing, and
verification in Rust.
# Documentation
Documentation is available [here](https://docs.rs/ed25519-dalek).
# Benchmarks
You need to pass the `--features="bench"` flag to run the benchmarks. The
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:
∃!isisⒶwintermute:(release/0.1.0 *$)~/code/rust/ed25519 ∴ cargo bench
Finished release [optimized] target(s) in 0.0 secs
Running target/release/deps/ed25519-0135748522c518d8
∃!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
running 5 tests
test ed25519::test::test_sign_verify ... ignored
test ed25519::test::test_unmarshal_marshal ... ignored
test ed25519::test::bench_key_generation ... bench: 54,837 ns/iter (+/- 11,613)
test ed25519::test::bench_sign ... bench: 69,735 ns/iter (+/- 21,902)
test ed25519::test::bench_verify ... bench: 183,891 ns/iter (+/- 75,304)
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)
test result: ok. 0 passed; 0 failed; 2 ignored; 3 measured
test result: ok. 0 passed; 0 failed; 3 ignored; 3 measured
In comparision, the equivalent package in Golang performs as follows:
In comparison, the equivalent package in Golang performs as follows:
∃!isisⒶwintermute:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
PASS
@ -34,37 +44,109 @@ In comparision, the equivalent package in Golang performs as follows:
Making key generation, signing, and verification a rough average of one third
faster, one fifth faster, and one eighth faster respectively. Of course, this
is just my machine, and these results—nowhere near rigorous—should be taken
with a fistful of salt.
with a handful of salt.
## Warning
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:
[Our elliptic curve library](https://github.com/isislovecruft/curve25519-dalek)
(which this code uses) has **not** yet received sufficient peer review by
other qualified cryptographers to be considered in any way, shape, or form,
safe.
∃!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
**USE AT YOUR OWN RISK**
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)
# Documentation
test result: ok. 0 passed; 0 failed; 3 ignored; 3 measured
Documentation is available [here](https://docs.rs/ed25519-dalek).
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, thanks to Rust, this implementation has both type and memory
safety. It's also easily readable a much larger set of people than those who
can read qhasm, making it more readily and more easily auditable. We're of
the opinion that, ultimately, these features—combined with speed—are more
valuable than simply cycle counts alone.
# Warnings
ed25519-dalek and
[our elliptic curve library](https://github.com/isislovecruft/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,
or form, safe.
**USE AT YOUR OWN RISK.**
### A Note on Signature Malleability
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)
We could eliminate the malleability property by multiplying by the curve
cofactor, however, this would cause our implementation to *not* match the
behaviour of every other implementation in existence. As of this writing,
[RFC 8032](https://tools.ietf.org/html/rfc8032), "Edwards-Curve Digital
Signature Algorithm (EdDSA)," advises that the stronger check should be done.
While we agree that the stronger check should be done, it is our opinion that
one shouldn't get to change the definition of "ed25519 verification" a decade
after the fact, breaking compatibility with every other implementation.
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
eventually support VXEdDSA in curve25519-dalek.
# Installation
To install, add the following to the dependencies section of your project's
`Cargo.toml`:
To install, add the following to your project's `Cargo.toml`:
ed25519-dalek = "^0.2"
[dependencies.ed25519-dalek]
version = "^0.3"
Then, in your library or executable source, add:
extern crate ed25519_dalek
To cause your application to build `ed25519-dalek` with the nightly feature
enabled by default, instead do:
[dependencies.ed25519-dalek]
version = "^0.3"
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"]
# TODO
* Maybe add methods to make exporting keys for backup easier.
* Benchmark in comparison to the ed25519_ref10 code.
* Maybe add methods to make exporting keys for backup easier. Maybe using
serde?
* 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
digest.
* Incorporate ed25519-dalek into Brian Smith's
[crypto-bench](https://github.com/briansmith/crypto-bench).

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -12,11 +12,12 @@
use core::fmt::Debug;
use sha2::{Digest, Sha512};
#[cfg(feature = "std")]
use rand::Rng;
use digest::Digest;
use generic_array::typenum::U64;
use curve25519_dalek::curve;
use curve25519_dalek::curve::BasepointMult;
use curve25519_dalek::curve::CompressedEdwardsY;
@ -25,6 +26,7 @@ use curve25519_dalek::curve::ProjectivePoint;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::subtle::arrays_equal_ct;
/// The length of an ed25519 `Signature`, in bytes.
pub const SIGNATURE_LENGTH: usize = 64;
/// An ed25519 signature.
@ -129,14 +131,15 @@ impl SecretKey {
///
/// A `SecretKey`.
#[inline]
#[allow(dead_code)]
fn from_bytes(bytes: &[u8]) -> SecretKey {
pub fn from_bytes(bytes: &[u8]) -> SecretKey {
SecretKey(*array_ref!(bytes, 0, 64))
}
/// Sign a message with this keypair's secret key.
pub fn sign(&self, message: &[u8]) -> Signature {
let mut h: Sha512 = Sha512::new();
pub fn sign<D>(&self, message: &[u8]) -> Signature
where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default();
let mut hash: [u8; 64] = [0u8; 64];
let mut signature_bytes: [u8; 64] = [0u8; SIGNATURE_LENGTH];
let mut expanded_key_secret: Scalar;
@ -157,7 +160,7 @@ impl SecretKey {
expanded_key_secret[31] &= 63;
expanded_key_secret[31] |= 64;
h = Sha512::new();
h = D::default();
h.input(&hash[32..]);
h.input(&message);
hash.copy_from_slice(h.result().as_slice());
@ -166,7 +169,7 @@ impl SecretKey {
r = ExtendedPoint::basepoint_mult(&mesg_digest);
h = Sha512::new();
h = D::default();
h.input(&r.compress_edwards().to_bytes()[..]);
h.input(public_key);
h.input(&message);
@ -225,8 +228,7 @@ impl PublicKey {
///
/// A `PublicKey`.
#[inline]
#[allow(dead_code)]
fn from_bytes(bytes: &[u8]) -> PublicKey {
pub fn from_bytes(bytes: &[u8]) -> PublicKey {
PublicKey(CompressedEdwardsY(*array_ref!(bytes, 0, 32)))
}
@ -242,12 +244,14 @@ impl PublicKey {
///
/// Returns true if the signature was successfully verified, and
/// false otherwise.
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
let mut h: Sha512 = Sha512::new();
pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool
where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default();
let mut a: ExtendedPoint;
let ao: Option<ExtendedPoint>;
let r: ProjectivePoint;
let mut digest: [u8; 64];
let digest: [u8; 64];
let digest_reduced: Scalar;
if signature.0[63] & 224 != 0 {
@ -262,16 +266,15 @@ impl PublicKey {
}
a = -(&a);
digest = [0u8; 64];
let top_half: &[u8; 32] = array_ref!(&signature.0, 32, 32);
let bottom_half: &[u8; 32] = array_ref!(&signature.0, 0, 32);
h.input(&bottom_half[..]);
h.input(&self.to_bytes());
h.input(&message);
digest.copy_from_slice(h.result().as_slice());
let digest_bytes = h.result();
digest = *array_ref!(digest_bytes, 0, 64);
digest_reduced = Scalar::reduce(&digest);
r = curve::double_scalar_mult_vartime(&digest_reduced, &a, &Scalar(*top_half));
@ -295,15 +298,45 @@ pub struct Keypair {
impl Keypair {
/// Generate an ed25519 keypair.
///
/// # Example
///
/// ```
/// extern crate rand;
/// extern crate sha2;
/// extern crate ed25519_dalek;
///
/// # fn main() {
///
/// use rand::Rng;
/// use rand::OsRng;
/// 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);
///
/// # }
/// ```
///
/// # Input
///
/// A CSPRING with a `fill_bytes()` method, e.g. the one returned
/// from `rand::OsRng::new()` (in the `rand` crate).
///
/// The caller must also supply a hash function which implements the
/// `Digest` and `Default` traits, and which returns 512 bits of output.
/// The standard hash function used for most ed25519 libraries is SHA-512,
/// which is available with `use sha2::Sha512` as in the example above.
/// Other suitable hash functions include Keccak-512 and Blake2b-512.
///
// we reassign 0 bytes to the temp variable t to overwrite it
#[cfg(feature = "std")]
#[allow(unused_assignments)]
pub fn generate<T: Rng>(cspring: &mut T) -> Keypair {
let mut h: Sha512 = Sha512::new();
pub fn generate<D>(cspring: &mut Rng) -> Keypair
where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default();
let mut hash: [u8; 64] = [0u8; 64];
let mut t: [u8; 32] = [0u8; 32];
let mut sk: [u8; 64] = [0u8; 64];
@ -335,13 +368,15 @@ impl Keypair {
}
/// Sign a message with this keypair's secret key.
pub fn sign(&self, message: &[u8]) -> Signature {
self.secret.sign(message)
pub fn sign<D>(&self, message: &[u8]) -> Signature
where D: Digest<OutputSize = U64> + Default {
self.secret.sign::<D>(message)
}
/// Verify a signature on a message with this keypair's public key.
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
self.public.verify(message, signature)
pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool
where D: Digest<OutputSize = U64> + Default {
self.public.verify::<D>(message, signature)
}
}
@ -352,34 +387,14 @@ mod test {
use std::fs::File;
use std::string::String;
use std::vec::Vec;
use test::Bencher;
use curve25519_dalek::curve::ExtendedPoint;
use rand::OsRng;
use rand::Rng;
use rustc_serialize::hex::FromHex;
use sha2::Sha512;
use super::*;
/// A fake RNG which simply returns zeroes.
struct ZeroRng;
impl ZeroRng {
fn new() -> ZeroRng {
ZeroRng
}
}
impl Rng for ZeroRng {
fn next_u32(&mut self) -> u32 { 0u32 }
fn fill_bytes(&mut self, bytes: &mut [u8]) {
for i in 0 .. bytes.len() {
bytes[i] = 0;
}
}
}
#[test]
fn test_unmarshal_marshal() { // TestUnmarshalMarshal
fn unmarshal_marshal() { // TestUnmarshalMarshal
let mut cspring: OsRng;
let mut keypair: Keypair;
let mut x: Option<ExtendedPoint>;
@ -390,7 +405,7 @@ mod test {
// from_bytes() fails if vx²-u=0 and vx²+u=0
loop {
keypair = Keypair::generate(&mut cspring);
keypair = Keypair::generate::<Sha512>(&mut cspring);
x = keypair.public.decompress();
if x.is_some() {
@ -404,7 +419,7 @@ mod test {
}
#[test]
fn test_sign_verify() { // TestSignVerify
fn sign_verify() { // TestSignVerify
let mut cspring: OsRng;
let keypair: Keypair;
let good_sig: Signature;
@ -414,15 +429,15 @@ mod test {
let bad: &[u8] = "wrong message".as_bytes();
cspring = OsRng::new().unwrap();
keypair = Keypair::generate(&mut cspring);
good_sig = keypair.sign(&good);
bad_sig = keypair.sign(&bad);
keypair = Keypair::generate::<Sha512>(&mut cspring);
good_sig = keypair.sign::<Sha512>(&good);
bad_sig = keypair.sign::<Sha512>(&bad);
assert!(keypair.verify(&good, &good_sig) == true,
assert!(keypair.verify::<Sha512>(&good, &good_sig) == true,
"Verification of a valid signature failed!");
assert!(keypair.verify(&good, &bad_sig) == false,
assert!(keypair.verify::<Sha512>(&good, &bad_sig) == false,
"Verification of a signature on a different message passed!");
assert!(keypair.verify(&bad, &good_sig) == false,
assert!(keypair.verify::<Sha512>(&bad, &good_sig) == false,
"Verification of a signature on a different message passed!");
}
@ -432,7 +447,7 @@ mod test {
#[cfg(test)]
#[cfg(not(release))]
#[test]
fn test_golden() { // TestGolden
fn golden() { // TestGolden
let mut line: String;
let mut lineno: usize = 0;
@ -465,40 +480,67 @@ mod test {
let secret_key: SecretKey = SecretKey::from_bytes(&sec_bytes);
let public_key: PublicKey = PublicKey::from_bytes(&pub_bytes);
let sig2: Signature = secret_key.sign(&message);
let sig2: Signature = secret_key.sign::<Sha512>(&message);
println!("{:?}", sec_bytes);
println!("{:?}", pub_bytes);
assert!(sig1 == sig2, "Signature bytes not equal on line {}", lineno);
assert!(public_key.verify(&message, &sig2), "Signature verification failed on line {}", lineno);
assert!(public_key.verify::<Sha512>(&message, &sig2),
"Signature verification failed on line {}", lineno);
}
}
}
#[cfg(all(test, feature = "bench"))]
mod bench {
use test::Bencher;
use rand::OsRng;
use sha2::Sha512;
use super::*;
/// A fake RNG which simply returns zeroes.
struct ZeroRng;
impl ZeroRng {
pub fn new() -> ZeroRng {
ZeroRng
}
}
impl Rng for ZeroRng {
fn next_u32(&mut self) -> u32 { 0u32 }
fn fill_bytes(&mut self, bytes: &mut [u8]) {
for i in 0 .. bytes.len() {
bytes[i] = 0;
}
}
}
#[bench]
fn bench_sign(b: &mut Bencher) {
fn sign(b: &mut Bencher) {
let mut cspring: OsRng = OsRng::new().unwrap();
let keypair: Keypair = Keypair::generate(&mut cspring);
let msg: &[u8] = "test message".as_bytes();
let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
let msg: &[u8] = b"";
b.iter(| | keypair.sign(msg));
b.iter(| | keypair.sign::<Sha512>(msg));
}
#[bench]
fn bench_verify(b: &mut Bencher) {
fn verify(b: &mut Bencher) {
let mut cspring: OsRng = OsRng::new().unwrap();
let keypair: Keypair = Keypair::generate(&mut cspring);
let msg: &[u8] = "test message".as_bytes();
let sig: Signature = keypair.sign(msg);
let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
let msg: &[u8] = b"";
let sig: Signature = keypair.sign::<Sha512>(msg);
b.iter(| | keypair.verify(msg, &sig));
b.iter(| | keypair.verify::<Sha512>(msg, &sig));
}
#[bench]
fn bench_key_generation(b: &mut Bencher) {
fn key_generation(b: &mut Bencher) {
let mut rng: ZeroRng = ZeroRng::new();
b.iter(| | Keypair::generate(&mut rng));
b.iter(| | Keypair::generate::<Sha512>(&mut rng));
}
}

View file

@ -14,60 +14,107 @@
//!
//! Creating an ed25519 signature on a message is simple.
//!
//! 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 random number generator (CSPRING). For
//! this example, we'll use the operating system's builtin PRNG to
//! generate a keypair:
//! 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
//! has 512 bits of output. For this example, we'll use the operating
//! system's builtin PRNG and SHA-512 to generate a keypair:
//!
//! ```ignore
//! ```
//! extern crate rand;
//! extern crate ed25519;
//! extern crate sha2;
//! extern crate ed25519_dalek;
//!
//! # fn main() {
//! use rand::Rng;
//! use rand::OsRng;
//! use ed25519::Keypair;
//! use ed25519::Signature;
//! use sha2::Sha512;
//! use ed25519_dalek::Keypair;
//! use ed25519_dalek::Signature;
//!
//! let mut cspring: OsRng = OsRng::new().unwrap();
//! let keypair: Keypair = Keypair::generate(&mut cspring);
//! let keypair: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # }
//! ```
//!
//! We can now use this `keypair` to sign a message:
//!
//! ```ignore
//! ```
//! # extern crate rand;
//! # extern crate sha2;
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # 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 message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
//! let signature: Signature = keypair.sign(message);
//! let signature: Signature = keypair.sign::<Sha512>(message);
//! # }
//! ```
//!
//! As well as to verify that this is, indeed, a valid signature on
//! that `message`:
//!
//! ```ignore
//! let verified: bool = keypair.verify(message, &signature);
//! ```
//! # extern crate rand;
//! # extern crate sha2;
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # 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 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);
//! # }
//! ```
//!
//! Anyone else, given the `public` half of the `keypair` can also easily
//! verify this signature:
//!
//! ```ignore
//! ```
//! # extern crate rand;
//! # extern crate sha2;
//! # extern crate ed25519_dalek;
//! # fn main() {
//! # use rand::Rng;
//! # use rand::OsRng;
//! # 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 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(message, &signature);
//! let verified: bool = public_key.verify::<Sha512>(message, &signature);
//!
//! assert!(verified);
//! # }
//! ```
#![no_std]
#![feature(rand)]
#![cfg_attr(feature = "nightly", feature(rand))]
#![allow(unused_features)]
#![feature(test)]
#![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)] // refuse to compile if documentation is missing
#[macro_use]
extern crate arrayref;
extern crate sha2;
extern crate curve25519_dalek;
extern crate generic_array;
extern crate digest;
#[cfg(feature = "std")]
extern crate rand;
@ -75,11 +122,17 @@ extern crate rand;
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;
extern crate sha2;
#[cfg(test)]
extern crate rustc_serialize;
#[cfg(all(test, feature = "bench"))]
extern crate test;
mod ed25519;
// Export everything public in ed25519.