mirror of
https://github.com/saymrwulf/betrusted-curve25519-dalek-source.git
synced 2026-09-05 20:30:54 +00:00
Merge branch 'release/0.8.0'
This commit is contained in:
commit
d472254ad3
7 changed files with 4501 additions and 30 deletions
11
Cargo.toml
11
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ed25519-dalek"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>"]
|
||||
readme = "README.md"
|
||||
license = "BSD-3-Clause"
|
||||
|
|
@ -16,12 +16,13 @@ exclude = [ ".gitignore", "TESTVECTORS", "res/*" ]
|
|||
travis-ci = { repository = "dalek-cryptography/ed25519-dalek", branch = "master"}
|
||||
|
||||
[dependencies.curve25519-dalek]
|
||||
version = "0.18"
|
||||
version = "0.19"
|
||||
default-features = false
|
||||
|
||||
[dependencies.rand]
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
features = ["i128_support"]
|
||||
|
||||
[dependencies.digest]
|
||||
version = "^0.7"
|
||||
|
|
@ -42,6 +43,9 @@ optional = true
|
|||
version = "^0.1.1"
|
||||
default-features = false
|
||||
|
||||
[dependencies.clear_on_drop]
|
||||
version = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "^0.3"
|
||||
sha2 = "^0.7"
|
||||
|
|
@ -56,7 +60,8 @@ harness = false
|
|||
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"]
|
||||
alloc = ["curve25519-dalek/alloc"]
|
||||
nightly = ["curve25519-dalek/nightly", "rand/nightly", "clear_on_drop/nightly"]
|
||||
asm = ["sha2/asm"]
|
||||
yolocrypto = ["curve25519-dalek/yolocrypto"]
|
||||
u64_backend = ["curve25519-dalek/u64_backend"]
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2017 Isis Agora Lovecruft. All rights reserved.
|
||||
Copyright (c) 2017-2018 Isis Agora Lovecruft. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
|
|
|||
57
README.md
57
README.md
|
|
@ -9,12 +9,7 @@ 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 i9-7900X running at 3.30 GHz, without TurboBoost, this code achieves
|
||||
On an Intel Skylake i9-7900X running at 3.30 GHz, without TurboBoost, this code achieves
|
||||
the following performance benchmarks:
|
||||
|
||||
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench
|
||||
|
|
@ -29,8 +24,8 @@ the following performance benchmarks:
|
|||
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"
|
||||
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
|
||||
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=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
|
||||
|
|
@ -40,7 +35,7 @@ the performance for signature verification is greatly improved:
|
|||
|
||||
In comparison, the equivalent package in Golang performs as follows:
|
||||
|
||||
∃!isisⒶwintermute:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
|
||||
∃!isisⒶmistakenot:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
|
||||
BenchmarkKeyGeneration 30000 47007 ns/op
|
||||
BenchmarkSigning 30000 48820 ns/op
|
||||
BenchmarkVerification 10000 119701 ns/op
|
||||
|
|
@ -60,6 +55,34 @@ 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.
|
||||
|
||||
If your protocol or application is able to batch signatures for verification,
|
||||
the `verify_batch()` function has greatly improved performance. On the
|
||||
aforementioned Intel Skylake i9-7900X, verifying a batch of 96 signatures takes
|
||||
1.7673ms. That's 18.4094us, or roughly 60750 cycles, per signature verification,
|
||||
more than double the speed of batch verification given in the original paper
|
||||
(this is likely not a fair comparison as that was a Nehalem machine).
|
||||
The numbers after the `/` in the test name refer to the size of the batch:
|
||||
|
||||
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
|
||||
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=avx2_backend batch
|
||||
Compiling ed25519-dalek v0.8.0 (file:///home/isis/code/rust/ed25519-dalek)
|
||||
Finished release [optimized] target(s) in 34.16s
|
||||
Running target/release/deps/ed25519_benchmarks-cf0daf7d68fc71b6
|
||||
Ed25519 batch signature verification/4 time: [105.20 us 106.04 us 106.99 us]
|
||||
Ed25519 batch signature verification/8 time: [178.66 us 179.01 us 179.39 us]
|
||||
Ed25519 batch signature verification/16 time: [325.65 us 326.67 us 327.90 us]
|
||||
Ed25519 batch signature verification/32 time: [617.96 us 620.74 us 624.12 us]
|
||||
Ed25519 batch signature verification/64 time: [1.1862 ms 1.1900 ms 1.1943 ms]
|
||||
Ed25519 batch signature verification/96 time: [1.7611 ms 1.7673 ms 1.7742 ms]
|
||||
Ed25519 batch signature verification/128 time: [2.3320 ms 2.3376 ms 2.3446 ms]
|
||||
Ed25519 batch signature verification/256 time: [5.0124 ms 5.0290 ms 5.0491 ms]
|
||||
|
||||
As you can see, there's an optimal batch size for each machine, so you'll likely
|
||||
want to your the benchmarks on your target CPU to discover the best size. For
|
||||
this machine, around 100 signatures per batch is the optimum:
|
||||
|
||||

|
||||
|
||||
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
|
||||
can read qhasm, making it more readily and more easily auditable. We're of
|
||||
|
|
@ -107,7 +130,7 @@ To install, add the following to your project's `Cargo.toml`:
|
|||
|
||||
```toml
|
||||
[dependencies.ed25519-dalek]
|
||||
version = "^0.7"
|
||||
version = "^0.8"
|
||||
```
|
||||
|
||||
Then, in your library or executable source, add:
|
||||
|
|
@ -123,7 +146,7 @@ enabled by default, instead do:
|
|||
|
||||
```toml
|
||||
[dependencies.ed25519-dalek]
|
||||
version = "^0.7"
|
||||
version = "^0.8"
|
||||
features = ["nightly"]
|
||||
```
|
||||
|
||||
|
|
@ -140,7 +163,7 @@ To enable [serde](https://serde.rs) support, build `ed25519-dalek` with:
|
|||
|
||||
```toml
|
||||
[dependencies.ed25519-dalek]
|
||||
version = "^0.7"
|
||||
version = "^0.8"
|
||||
features = ["serde"]
|
||||
```
|
||||
|
||||
|
|
@ -152,13 +175,3 @@ likely want to compile with
|
|||
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 bzero it before mutating to store the
|
||||
digest.
|
||||
* Incorporate ed25519-dalek into Brian Smith's
|
||||
[crypto-bench](https://github.com/briansmith/crypto-bench).
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ mod ed25519_benches {
|
|||
use super::*;
|
||||
use ed25519_dalek::ExpandedSecretKey;
|
||||
use ed25519_dalek::Keypair;
|
||||
use ed25519_dalek::PublicKey;
|
||||
use ed25519_dalek::Signature;
|
||||
use ed25519_dalek::verify_batch;
|
||||
use rand::thread_rng;
|
||||
use rand::ThreadRng;
|
||||
use sha2::Sha512;
|
||||
|
|
@ -56,6 +58,25 @@ mod ed25519_benches {
|
|||
});
|
||||
}
|
||||
|
||||
fn verify_batch_signatures(c: &mut Criterion) {
|
||||
static BATCH_SIZES: [usize; 8] = [4, 8, 16, 32, 64, 96, 128, 256];
|
||||
|
||||
c.bench_function_over_inputs(
|
||||
"Ed25519 batch signature verification",
|
||||
|b, &&size| {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let keypairs: Vec<Keypair> = (0..size).map(|_| Keypair::generate::<Sha512, _>(&mut csprng)).collect();
|
||||
let msg: &[u8] = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
let messages: Vec<&[u8]> = (0..size).map(|_| msg).collect();
|
||||
let signatures: Vec<Signature> = keypairs.iter().map(|key| key.sign::<Sha512>(&msg)).collect();
|
||||
let public_keys: Vec<PublicKey> = keypairs.iter().map(|key| key.public).collect();
|
||||
|
||||
b.iter(|| verify_batch::<Sha512>(&messages[..], &signatures[..], &public_keys[..]));
|
||||
},
|
||||
&BATCH_SIZES,
|
||||
);
|
||||
}
|
||||
|
||||
fn key_generation(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
|
||||
|
|
@ -71,6 +92,7 @@ mod ed25519_benches {
|
|||
sign,
|
||||
sign_expanded_key,
|
||||
verify,
|
||||
verify_batch_signatures,
|
||||
key_generation,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4251
res/batch-violin-benchmark.svg
Normal file
4251
res/batch-violin-benchmark.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 511 KiB |
185
src/ed25519.rs
185
src/ed25519.rs
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of ed25519-dalek.
|
||||
// Copyright (c) 2017 Isis Lovecruft
|
||||
// Copyright (c) 2017-2018 Isis Lovecruft
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
//! A Rust implementation of ed25519 EdDSA key generation, signing, and
|
||||
//! verification.
|
||||
|
||||
use core::default::Default;
|
||||
use core::fmt::{Debug};
|
||||
|
||||
use rand::CryptoRng;
|
||||
|
|
@ -27,6 +28,8 @@ use serde::de::Visitor;
|
|||
#[cfg(feature = "sha2")]
|
||||
use sha2::Sha512;
|
||||
|
||||
use clear_on_drop::clear::Clear;
|
||||
|
||||
use digest::Digest;
|
||||
|
||||
use generic_array::typenum::U64;
|
||||
|
|
@ -165,6 +168,7 @@ impl<'d> Deserialize<'d> for Signature {
|
|||
|
||||
/// An EdDSA secret key.
|
||||
#[repr(C)]
|
||||
#[derive(Default)] // we derive Default in order to use the clear() method in Drop
|
||||
pub struct SecretKey(pub (crate) [u8; SECRET_KEY_LENGTH]);
|
||||
|
||||
impl Debug for SecretKey {
|
||||
|
|
@ -173,6 +177,13 @@ impl Debug for SecretKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// Overwrite secret key material with null bytes when it goes out of scope.
|
||||
impl Drop for SecretKey {
|
||||
fn drop(&mut self) {
|
||||
self.0.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl SecretKey {
|
||||
/// Expand this `SecretKey` into an `ExpandedSecretKey`.
|
||||
pub fn expand<D>(&self) -> ExpandedSecretKey where D: Digest<OutputSize = U64> + Default {
|
||||
|
|
@ -370,11 +381,20 @@ impl<'d> Deserialize<'d> for SecretKey {
|
|||
// better-designed, Schnorr-based signature scheme, see Trevor Perrin's work on
|
||||
// "generalised EdDSA" and "VXEdDSA".
|
||||
#[repr(C)]
|
||||
#[derive(Default)] // we derive Default in order to use the clear() method in Drop
|
||||
pub struct ExpandedSecretKey {
|
||||
pub (crate) key: Scalar,
|
||||
pub (crate) nonce: [u8; 32],
|
||||
}
|
||||
|
||||
/// Overwrite secret key material with null bytes when it goes out of scope.
|
||||
impl Drop for ExpandedSecretKey {
|
||||
fn drop(&mut self) {
|
||||
self.key.clear();
|
||||
self.nonce.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sha2")]
|
||||
impl<'a> From<&'a SecretKey> for ExpandedSecretKey {
|
||||
/// Construct an `ExpandedSecretKey` from a `SecretKey`.
|
||||
|
|
@ -683,7 +703,7 @@ impl<'d> Deserialize<'d> for ExpandedSecretKey {
|
|||
}
|
||||
|
||||
/// An ed25519 public key.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Default, Eq, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct PublicKey(pub (crate) CompressedEdwardsY);
|
||||
|
||||
|
|
@ -865,6 +885,119 @@ impl PublicKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// Verify a batch of `signatures` on `messages` with their respective `public_keys`.
|
||||
///
|
||||
/// # Inputs
|
||||
///
|
||||
/// * `messages` is a slice of byte slices, one per signed message.
|
||||
/// * `signatures` is a slice of `Signature`s.
|
||||
/// * `public_keys` is a slice of `PublicKey`s.
|
||||
/// * `csprng` is an implementation of `Rng + CryptoRng`, such as `rand::ThreadRng`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the `messages, `signatures`, and `public_keys`
|
||||
/// slices are not equal length.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * A `Result` whose `Ok` value is an emtpy tuple and whose `Err` value is a
|
||||
/// `SignatureError` containing a description of the internal error which
|
||||
/// occured.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// extern crate ed25519_dalek;
|
||||
/// extern crate rand;
|
||||
/// extern crate sha2;
|
||||
///
|
||||
/// use ed25519_dalek::verify_batch;
|
||||
/// use ed25519_dalek::Keypair;
|
||||
/// use ed25519_dalek::PublicKey;
|
||||
/// use ed25519_dalek::Signature;
|
||||
/// use rand::thread_rng;
|
||||
/// use rand::ThreadRng;
|
||||
/// use sha2::Sha512;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut csprng: ThreadRng = thread_rng();
|
||||
/// let keypairs: Vec<Keypair> = (0..64).map(|_| Keypair::generate::<Sha512, _>(&mut csprng)).collect();
|
||||
/// let msg: &[u8] = b"They're good dogs Brant";
|
||||
/// let messages: Vec<&[u8]> = (0..64).map(|_| msg).collect();
|
||||
/// let signatures: Vec<Signature> = keypairs.iter().map(|key| key.sign::<Sha512>(&msg)).collect();
|
||||
/// let public_keys: Vec<PublicKey> = keypairs.iter().map(|key| key.public).collect();
|
||||
///
|
||||
/// let result = verify_batch::<Sha512>(&messages[..], &signatures[..], &public_keys[..]);
|
||||
/// assert!(result.is_ok());
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn verify_batch<D>(messages: &[&[u8]],
|
||||
signatures: &[Signature],
|
||||
public_keys: &[PublicKey]) -> Result<(), SignatureError>
|
||||
where D: Digest<OutputSize = U64> + Default
|
||||
{
|
||||
const ASSERT_MESSAGE: &'static [u8] = b"The number of messages, signatures, and public keys must be equal.";
|
||||
assert!(signatures.len() == messages.len(), ASSERT_MESSAGE);
|
||||
assert!(signatures.len() == public_keys.len(), ASSERT_MESSAGE);
|
||||
assert!(public_keys.len() == messages.len(), ASSERT_MESSAGE);
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(feature = "std")]
|
||||
use std::vec::Vec;
|
||||
|
||||
use core::iter::once;
|
||||
use rand::thread_rng;
|
||||
|
||||
use curve25519_dalek::traits::IsIdentity;
|
||||
use curve25519_dalek::traits::VartimeMultiscalarMul;
|
||||
|
||||
// Select a random 128-bit scalar for each signature.
|
||||
let zs: Vec<Scalar> = signatures
|
||||
.iter()
|
||||
.map(|_| Scalar::from(thread_rng().gen::<u128>()))
|
||||
.collect();
|
||||
|
||||
// Compute the basepoint coefficient, ∑ s[i]z[i] (mod l)
|
||||
let B_coefficient: Scalar = signatures
|
||||
.iter()
|
||||
.map(|sig| sig.s)
|
||||
.zip(zs.iter())
|
||||
.map(|(s, z)| z * s)
|
||||
.sum();
|
||||
|
||||
// Compute H(R || A || M) for each (signature, public_key, message) triplet
|
||||
let hrams = (0..signatures.len()).map(|i| {
|
||||
let mut h: D = D::default();
|
||||
h.input(signatures[i].R.as_bytes());
|
||||
h.input(public_keys[i].as_bytes());
|
||||
h.input(&messages[i]);
|
||||
Scalar::from_hash(h)
|
||||
});
|
||||
|
||||
// Multiply each H(R || A || M) by the random value
|
||||
let zhrams = hrams.zip(zs.iter()).map(|(hram, z)| hram * z);
|
||||
|
||||
let Rs = signatures.iter().map(|sig| sig.R.decompress());
|
||||
let As = public_keys.iter().map(|pk| pk.0.decompress());
|
||||
let B = once(Some(constants::ED25519_BASEPOINT_POINT));
|
||||
|
||||
// Compute (-∑ z[i]s[i] (mod l)) B + ∑ z[i]R[i] + ∑ (z[i]H(R||A||M)[i] (mod l)) A[i] = 0
|
||||
let id = EdwardsPoint::optional_multiscalar_mul(
|
||||
once(-B_coefficient).chain(zs.iter().cloned()).chain(zhrams),
|
||||
B.chain(Rs).chain(As),
|
||||
).ok_or_else(|| SignatureError(InternalError::VerifyError))?;
|
||||
|
||||
if id.is_identity() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SignatureError(InternalError::VerifyError))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl Serialize for PublicKey {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||
|
|
@ -894,7 +1027,7 @@ impl<'d> Deserialize<'d> for PublicKey {
|
|||
}
|
||||
|
||||
/// An ed25519 keypair.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)] // we derive Default in order to use the clear() method in Drop
|
||||
#[repr(C)]
|
||||
pub struct Keypair {
|
||||
/// The secret half of this keypair.
|
||||
|
|
@ -1224,8 +1357,10 @@ mod test {
|
|||
use std::fs::File;
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
use rand::thread_rng;
|
||||
use rand::ChaChaRng;
|
||||
use rand::SeedableRng;
|
||||
use rand::ThreadRng;
|
||||
use hex::FromHex;
|
||||
use sha2::Sha512;
|
||||
use super::*;
|
||||
|
|
@ -1396,6 +1531,32 @@ mod test {
|
|||
"Verification of a signature on a different message passed!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_batch_seven_signatures() {
|
||||
let messages: [&[u8]; 7] = [
|
||||
b"Watch closely everyone, I'm going to show you how to kill a god.",
|
||||
b"I'm not a cryptographer I just encrypt a lot.",
|
||||
b"Still not a cryptographer.",
|
||||
b"This is a test of the tsunami alert system. This is only a test.",
|
||||
b"Fuck dumbin' it down, spit ice, skip jewellery: Molotov cocktails on me like accessories.",
|
||||
b"Hey, I never cared about your bucks, so if I run up with a mask on, probably got a gas can too.",
|
||||
b"And I'm not here to fill 'er up. Nope, we came to riot, here to incite, we don't want any of your stuff.", ];
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let mut keypairs: Vec<Keypair> = Vec::new();
|
||||
let mut signatures: Vec<Signature> = Vec::new();
|
||||
|
||||
for i in 0..messages.len() {
|
||||
let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
|
||||
signatures.push(keypair.sign::<Sha512>(&messages[i]));
|
||||
keypairs.push(keypair);
|
||||
}
|
||||
let public_keys: Vec<PublicKey> = keypairs.iter().map(|key| key.public).collect();
|
||||
|
||||
let result = verify_batch::<Sha512>(&messages, &signatures[..], &public_keys[..]);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_key_from_bytes() {
|
||||
// Make another function so that we can test the ? operator.
|
||||
|
|
@ -1416,6 +1577,24 @@ mod test {
|
|||
175, 002, 026, 104, 247, 007, 081, 026, ]))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keypair_clear_on_drop() {
|
||||
let mut keypair: Keypair = Keypair::from_bytes(&[15u8; KEYPAIR_LENGTH][..]).unwrap();
|
||||
|
||||
keypair.clear();
|
||||
|
||||
fn as_bytes<T>(x: &T) -> &[u8] {
|
||||
use core::mem;
|
||||
use core::slice;
|
||||
|
||||
unsafe {
|
||||
slice::from_raw_parts(x as *const T as *const u8, mem::size_of_val(x))
|
||||
}
|
||||
}
|
||||
|
||||
assert!(!as_bytes(&keypair).contains(&0x15));
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "serde"))]
|
||||
use bincode::{serialize, deserialize, Infinite};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of ed25519-dalek.
|
||||
// Copyright (c) 2017 Isis Lovecruft
|
||||
// Copyright (c) 2017-2018 Isis Lovecruft
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -264,6 +264,7 @@ extern crate generic_array;
|
|||
extern crate digest;
|
||||
extern crate failure;
|
||||
extern crate rand;
|
||||
extern crate clear_on_drop;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
#[macro_use]
|
||||
|
|
|
|||
Loading…
Reference in a new issue