Fix batch build (#220)
* Fixed bench when `batch` feature is not present * Added bench build regression test to CI * Fixed batch build more generally * Simplified batch cfg gates in benches * Updated criterion * Made CI batch-nondeterministic test use nostd * Fix batch_deterministic build * Removed bad compile error when batch and batch_deterministic are selected
This commit is contained in:
parent
616d55c36c
commit
e2ed3133a6
9
.github/workflows/rust.yml
vendored
9
.github/workflows/rust.yml
vendored
@ -2,9 +2,9 @@ name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
branches: [ '**' ]
|
||||
pull_request:
|
||||
branches: [ 'main', 'develop', 'release/2.0' ]
|
||||
branches: [ '**' ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@ -32,7 +32,7 @@ jobs:
|
||||
- run: cargo test --target ${{ matrix.target }} --features batch
|
||||
- run: cargo test --target ${{ matrix.target }} --features batch_deterministic
|
||||
- run: cargo test --target ${{ matrix.target }} --features serde
|
||||
- run: cargo test --target ${{ matrix.target }} --features pkcs8
|
||||
- run: cargo test --target ${{ matrix.target }} --features pem
|
||||
|
||||
build-simd:
|
||||
name: Test simd backend (nightly)
|
||||
@ -68,6 +68,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo build --benches --features batch
|
||||
- run: cargo build --benches --features batch_deterministic
|
||||
|
||||
rustfmt:
|
||||
name: Check formatting
|
||||
@ -87,4 +88,4 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@1.65
|
||||
with:
|
||||
components: clippy
|
||||
- run: cargo clippy
|
||||
- run: cargo clippy
|
||||
|
@ -28,7 +28,7 @@ curve25519-dalek = { version = "=4.0.0-pre.3", default-features = false, feature
|
||||
ed25519 = { version = "=2.0.0-pre.1", default-features = false }
|
||||
merlin = { version = "3", default-features = false, optional = true }
|
||||
rand = { version = "0.8", default-features = false, optional = true }
|
||||
rand_core = { version = "0.6", default-features = false, optional = true }
|
||||
rand_core = { version = "0.6.4", default-features = false, optional = true }
|
||||
serde = { version = "1.0", default-features = false, optional = true }
|
||||
serde_bytes = { version = "0.11", optional = true }
|
||||
sha2 = { version = "0.10", default-features = false }
|
||||
@ -38,16 +38,16 @@ zeroize = { version = "1.5", default-features = false }
|
||||
hex = "0.4"
|
||||
bincode = "1.0"
|
||||
serde_json = "1.0"
|
||||
criterion = "0.3"
|
||||
criterion = { version = "0.4", features = ["html_reports"] }
|
||||
hex-literal = "0.3"
|
||||
rand = "0.8"
|
||||
rand_core = { version = "0.6.4", default-features = false }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
toml = { version = "0.5" }
|
||||
|
||||
[[bench]]
|
||||
name = "ed25519_benchmarks"
|
||||
harness = false
|
||||
required-features = ["batch"]
|
||||
|
||||
[features]
|
||||
default = ["std", "rand"]
|
||||
@ -55,7 +55,7 @@ alloc = ["curve25519-dalek/alloc", "ed25519/alloc", "rand?/alloc", "serde?/alloc
|
||||
std = ["alloc", "ed25519/std", "rand?/std", "serde?/std", "sha2/std"]
|
||||
|
||||
asm = ["sha2/asm"]
|
||||
batch = ["alloc", "merlin", "rand/std"]
|
||||
batch = ["alloc", "merlin", "rand"]
|
||||
# This feature enables deterministic batch verification.
|
||||
batch_deterministic = ["alloc", "merlin", "rand"]
|
||||
# This features turns off stricter checking for scalar malleability in signatures
|
||||
|
@ -261,8 +261,12 @@ comprising either avx2 or avx512 backends. To use them, compile with
|
||||
|
||||
The standard variants of batch signature verification (i.e. many signatures made
|
||||
with potentially many different public keys over potentially many different
|
||||
message) is available via the `batch` feature. It uses synthetic randomness, as
|
||||
noted above.
|
||||
messages) is available via the `batch` feature. It uses synthetic randomness, as
|
||||
noted above. Batch verification requires allocation, so this won't function in
|
||||
heapless settings.
|
||||
|
||||
Batch verification is slightly faster with the `std` feature enabled, since it
|
||||
permits us to use `rand::thread_rng`.
|
||||
|
||||
### Deterministic Batch Signature Verification
|
||||
|
||||
|
@ -7,15 +7,13 @@
|
||||
// Authors:
|
||||
// - isis agora lovecruft <isis@patternsinthevoid.net>
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use criterion::{criterion_group, Criterion};
|
||||
|
||||
mod ed25519_benches {
|
||||
use super::*;
|
||||
use ed25519_dalek::verify_batch;
|
||||
use ed25519_dalek::Signature;
|
||||
use ed25519_dalek::Signer;
|
||||
use ed25519_dalek::SigningKey;
|
||||
use ed25519_dalek::VerifyingKey;
|
||||
use rand::prelude::ThreadRng;
|
||||
use rand::thread_rng;
|
||||
|
||||
@ -49,14 +47,17 @@ mod ed25519_benches {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "batch", feature = "batch_deterministic"))]
|
||||
fn verify_batch_signatures(c: &mut Criterion) {
|
||||
use ed25519_dalek::verify_batch;
|
||||
|
||||
static BATCH_SIZES: [usize; 8] = [4, 8, 16, 32, 64, 96, 128, 256];
|
||||
|
||||
// TODO: use BenchmarkGroups instead.
|
||||
#[allow(deprecated)]
|
||||
c.bench_function_over_inputs(
|
||||
"Ed25519 batch signature verification",
|
||||
|b, &&size| {
|
||||
// Benchmark batch verification for all the above batch sizes
|
||||
let mut group = c.benchmark_group("Ed25519 batch signature verification");
|
||||
for size in BATCH_SIZES {
|
||||
let name = format!("size={size}");
|
||||
group.bench_function(name, |b| {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let keypairs: Vec<SigningKey> = (0..size)
|
||||
.map(|_| SigningKey::generate(&mut csprng))
|
||||
@ -65,15 +66,18 @@ mod ed25519_benches {
|
||||
let messages: Vec<&[u8]> = (0..size).map(|_| msg).collect();
|
||||
let signatures: Vec<Signature> =
|
||||
keypairs.iter().map(|key| key.sign(&msg)).collect();
|
||||
let verifying_keys: Vec<VerifyingKey> =
|
||||
let verifying_keys: Vec<_> =
|
||||
keypairs.iter().map(|key| key.verifying_key()).collect();
|
||||
|
||||
b.iter(|| verify_batch(&messages[..], &signatures[..], &verifying_keys[..]));
|
||||
},
|
||||
&BATCH_SIZES,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If the above function isn't defined, make a placeholder function
|
||||
#[cfg(not(any(feature = "batch", feature = "batch_deterministic")))]
|
||||
fn verify_batch_signatures(_: &mut Criterion) {}
|
||||
|
||||
fn key_generation(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
|
||||
@ -94,4 +98,4 @@ mod ed25519_benches {
|
||||
}
|
||||
}
|
||||
|
||||
criterion_main!(ed25519_benches::ed25519_benches);
|
||||
criterion::criterion_main!(ed25519_benches::ed25519_benches);
|
||||
|
60
src/batch.rs
60
src/batch.rs
@ -27,11 +27,7 @@ pub use curve25519_dalek::digest::Digest;
|
||||
|
||||
use merlin::Transcript;
|
||||
|
||||
#[cfg(all(feature = "batch", not(feature = "batch_deterministic")))]
|
||||
use rand::thread_rng;
|
||||
use rand::Rng;
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
use rand_core;
|
||||
|
||||
use sha2::Sha512;
|
||||
|
||||
@ -40,6 +36,19 @@ use crate::errors::SignatureError;
|
||||
use crate::signature::InternalSignature;
|
||||
use crate::VerifyingKey;
|
||||
|
||||
/// Gets an RNG from the system, or the zero RNG if we're in deterministic mode. If available, we
|
||||
/// prefer `thread_rng`, since it's faster than `OsRng`.
|
||||
fn get_rng() -> impl rand_core::CryptoRngCore {
|
||||
#[cfg(all(feature = "batch_deterministic", not(feature = "batch")))]
|
||||
return ZeroRng;
|
||||
|
||||
#[cfg(all(feature = "batch", feature = "std"))]
|
||||
return rand::thread_rng();
|
||||
|
||||
#[cfg(all(feature = "batch", not(feature = "std")))]
|
||||
return rand::rngs::OsRng;
|
||||
}
|
||||
|
||||
trait BatchTranscript {
|
||||
fn append_scalars(&mut self, scalars: &Vec<Scalar>);
|
||||
fn append_message_lengths(&mut self, message_lengths: &Vec<usize>);
|
||||
@ -63,10 +72,9 @@ impl BatchTranscript for Transcript {
|
||||
|
||||
/// Append the lengths of the messages into the transcript.
|
||||
///
|
||||
/// This is done out of an (potential over-)abundance of caution, to guard
|
||||
/// against the unlikely event of collisions. However, a nicer way to do
|
||||
/// this would be to append the message length before the message, but this
|
||||
/// is messy w.r.t. the calculations of the `H(R||A||M)`s above.
|
||||
/// This is done out of an (potential over-)abundance of caution, to guard against the unlikely
|
||||
/// event of collisions. However, a nicer way to do this would be to append the message length
|
||||
/// before the message, but this is messy w.r.t. the calculations of the `H(R||A||M)`s above.
|
||||
fn append_message_lengths(&mut self, message_lengths: &Vec<usize>) {
|
||||
for (i, len) in message_lengths.iter().enumerate() {
|
||||
self.append_u64(b"", i as u64);
|
||||
@ -75,13 +83,12 @@ impl BatchTranscript for Transcript {
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of `rand_core::RngCore` which does nothing, to provide
|
||||
/// purely deterministic transcript-based nonces, rather than synthetically
|
||||
/// random nonces.
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
struct ZeroRng {}
|
||||
/// An implementation of `rand_core::RngCore` which does nothing, to provide purely deterministic
|
||||
/// transcript-based nonces, rather than synthetically random nonces.
|
||||
#[cfg(feature = "batch_deterministic")]
|
||||
struct ZeroRng;
|
||||
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
#[cfg(feature = "batch_deterministic")]
|
||||
impl rand_core::RngCore for ZeroRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
rand_core::impls::next_u32_via_fill(self)
|
||||
@ -107,14 +114,9 @@ impl rand_core::RngCore for ZeroRng {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
#[cfg(feature = "batch_deterministic")]
|
||||
impl rand_core::CryptoRng for ZeroRng {}
|
||||
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
fn zero_rng() -> ZeroRng {
|
||||
ZeroRng {}
|
||||
}
|
||||
|
||||
/// Verify a batch of `signatures` on `messages` with their respective `verifying_keys`.
|
||||
///
|
||||
/// # Inputs
|
||||
@ -199,7 +201,7 @@ fn zero_rng() -> ZeroRng {
|
||||
/// use rand::rngs::OsRng;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut csprng = OsRng{};
|
||||
/// let mut csprng = OsRng;
|
||||
/// let signing_keys: Vec<_> = (0..64).map(|_| SigningKey::generate(&mut csprng)).collect();
|
||||
/// let msg: &[u8] = b"They're good dogs Brant";
|
||||
/// let messages: Vec<&[u8]> = (0..64).map(|_| msg).collect();
|
||||
@ -249,25 +251,21 @@ pub fn verify_batch(
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Collect the message lengths and the scalar portions of the signatures,
|
||||
// and add them into the transcript.
|
||||
// Collect the message lengths and the scalar portions of the signatures, and add them into the
|
||||
// transcript.
|
||||
let message_lengths: Vec<usize> = messages.iter().map(|i| i.len()).collect();
|
||||
let scalars: Vec<Scalar> = signatures.iter().map(|i| i.s).collect();
|
||||
|
||||
// Build a PRNG based on a transcript of the H(R || A || M)s seen thus far.
|
||||
// This provides synthethic randomness in the default configuration, and
|
||||
// purely deterministic in the case of compiling with the
|
||||
// "batch_deterministic" feature.
|
||||
// Build a PRNG based on a transcript of the H(R || A || M)s seen thus far. This provides
|
||||
// synthethic randomness in the default configuration, and purely deterministic in the case of
|
||||
// compiling with the "batch_deterministic" feature.
|
||||
let mut transcript: Transcript = Transcript::new(b"ed25519 batch verification");
|
||||
|
||||
transcript.append_scalars(&hrams);
|
||||
transcript.append_message_lengths(&message_lengths);
|
||||
transcript.append_scalars(&scalars);
|
||||
|
||||
#[cfg(all(feature = "batch", not(feature = "batch_deterministic")))]
|
||||
let mut prng = transcript.build_rng().finalize(&mut thread_rng());
|
||||
#[cfg(all(not(feature = "batch"), feature = "batch_deterministic"))]
|
||||
let mut prng = transcript.build_rng().finalize(&mut zero_rng());
|
||||
let mut prng = transcript.build_rng().finalize(&mut get_rng());
|
||||
|
||||
// Select a random 128-bit scalar for each signature.
|
||||
let zs: Vec<Scalar> = signatures
|
||||
|
50
src/lib.rs
50
src/lib.rs
@ -18,28 +18,26 @@
|
||||
//! secure pseudorandom number generator (CSPRNG). For this example, we'll use
|
||||
//! the operating system's builtin PRNG:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[cfg(feature = "std")]
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! use rand::rngs::OsRng;
|
||||
//! use ed25519_dalek::SigningKey;
|
||||
//! use ed25519_dalek::Signature;
|
||||
//!
|
||||
//! let mut csprng = OsRng{};
|
||||
//! let mut csprng = OsRng;
|
||||
//! let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! # }
|
||||
//! #
|
||||
//! # #[cfg(not(feature = "std"))]
|
||||
//! # fn main() { }
|
||||
//! ```
|
||||
//!
|
||||
//! We can now use this `signing_key` to sign a message:
|
||||
//!
|
||||
//! ```
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::SigningKey;
|
||||
//! # let mut csprng = OsRng{};
|
||||
//! # let mut csprng = OsRng;
|
||||
//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! use ed25519_dalek::{Signature, Signer};
|
||||
//! let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||
@ -50,11 +48,12 @@
|
||||
//! As well as to verify that this is, indeed, a valid signature on
|
||||
//! that `message`:
|
||||
//!
|
||||
//! ```
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::{SigningKey, Signature, Signer};
|
||||
//! # let mut csprng = OsRng{};
|
||||
//! # let mut csprng = OsRng;
|
||||
//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||
//! # let signature: Signature = signing_key.sign(message);
|
||||
@ -66,7 +65,8 @@
|
||||
//! Anyone else, given the `public` half of the `signing_key` can also easily
|
||||
//! verify this signature:
|
||||
//!
|
||||
//! ```
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::SigningKey;
|
||||
@ -91,7 +91,8 @@
|
||||
//! secret key to anyone else, since they will only need the public key to
|
||||
//! verify your signatures!)
|
||||
//!
|
||||
//! ```
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey};
|
||||
@ -110,14 +111,15 @@
|
||||
//!
|
||||
//! And similarly, decoded from bytes with `::from_bytes()`:
|
||||
//!
|
||||
//! ```
|
||||
#![cfg_attr(feature = "rand", doc = "```")]
|
||||
#![cfg_attr(not(feature = "rand"), doc = "```ignore")]
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use std::convert::TryInto;
|
||||
//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey, SecretKey, SignatureError};
|
||||
//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
|
||||
//! # fn do_test() -> Result<(SigningKey, VerifyingKey, Signature), SignatureError> {
|
||||
//! # let mut csprng = OsRng{};
|
||||
//! # let mut csprng = OsRng;
|
||||
//! # let signing_key_orig: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||
//! # let signature_orig: Signature = signing_key_orig.sign(message);
|
||||
@ -164,13 +166,13 @@
|
||||
//!
|
||||
#![cfg_attr(feature = "pem", doc = "```")]
|
||||
#![cfg_attr(not(feature = "pem"), doc = "```ignore")]
|
||||
//! use ed25519_dalek::{VerifyingKey, pkcs8::DecodeVerifyingKey};
|
||||
//! use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey};
|
||||
//!
|
||||
//! let pem = "-----BEGIN PUBLIC KEY-----
|
||||
//! MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
|
||||
//! -----END PUBLIC KEY-----";
|
||||
//!
|
||||
//! let verifying_key = VerifyingKey::from_verifying_key_pem(pem)
|
||||
//! let verifying_key = VerifyingKey::from_public_key_pem(pem)
|
||||
//! .expect("invalid public key PEM");
|
||||
//! ```
|
||||
//!
|
||||
@ -187,13 +189,13 @@
|
||||
//! They can be then serialised into any of the wire formats which serde supports.
|
||||
//! For example, using [bincode](https://github.com/TyOverby/bincode):
|
||||
//!
|
||||
//! ```
|
||||
//! # #[cfg(feature = "serde")]
|
||||
#![cfg_attr(all(feature = "rand", feature = "serde"), doc = "```")]
|
||||
#![cfg_attr(not(all(feature = "rand", feature = "serde")), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey};
|
||||
//! use bincode::serialize;
|
||||
//! # let mut csprng = OsRng{};
|
||||
//! # let mut csprng = OsRng;
|
||||
//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||
//! # let signature: Signature = signing_key.sign(message);
|
||||
@ -203,22 +205,20 @@
|
||||
//! let encoded_verifying_key: Vec<u8> = serialize(&verifying_key).unwrap();
|
||||
//! let encoded_signature: Vec<u8> = serialize(&signature).unwrap();
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "serde"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! After sending the `encoded_verifying_key` and `encoded_signature`, the
|
||||
//! recipient may deserialise them and verify:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[cfg(feature = "serde")]
|
||||
#![cfg_attr(all(feature = "rand", feature = "serde"), doc = "```")]
|
||||
#![cfg_attr(not(all(feature = "rand", feature = "serde")), doc = "```ignore")]
|
||||
//! # fn main() {
|
||||
//! # use rand::rngs::OsRng;
|
||||
//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey};
|
||||
//! # use bincode::serialize;
|
||||
//! use bincode::deserialize;
|
||||
//!
|
||||
//! # let mut csprng = OsRng{};
|
||||
//! # let mut csprng = OsRng;
|
||||
//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
//! let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||
//! # let signature: Signature = signing_key.sign(message);
|
||||
@ -236,8 +236,6 @@
|
||||
//!
|
||||
//! assert!(verified);
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "serde"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
#![no_std]
|
||||
|
@ -13,7 +13,7 @@
|
||||
use ed25519::pkcs8::{self, DecodePrivateKey};
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand_core::CryptoRngCore;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::de::Error as SerdeError;
|
||||
@ -168,7 +168,7 @@ impl SigningKey {
|
||||
/// use ed25519_dalek::SigningKey;
|
||||
/// use ed25519_dalek::Signature;
|
||||
///
|
||||
/// let mut csprng = OsRng{};
|
||||
/// let mut csprng = OsRng;
|
||||
/// let signing_key: SigningKey = SigningKey::generate(&mut csprng);
|
||||
///
|
||||
/// # }
|
||||
@ -187,10 +187,7 @@ impl SigningKey {
|
||||
/// which is available with `use sha2::Sha512` as in the example above.
|
||||
/// Other suitable hash functions include Keccak-512 and Blake2b-512.
|
||||
#[cfg(feature = "rand")]
|
||||
pub fn generate<R>(csprng: &mut R) -> SigningKey
|
||||
where
|
||||
R: CryptoRng + RngCore,
|
||||
{
|
||||
pub fn generate<R: CryptoRngCore + ?Sized>(csprng: &mut R) -> SigningKey {
|
||||
let mut secret = SecretKey::default();
|
||||
csprng.fill_bytes(&mut secret);
|
||||
Self::from_bytes(&secret)
|
||||
|
@ -209,7 +209,7 @@ mod integrations {
|
||||
let good: &[u8] = "test message".as_bytes();
|
||||
let bad: &[u8] = "wrong message".as_bytes();
|
||||
|
||||
let mut csprng = OsRng {};
|
||||
let mut csprng = OsRng;
|
||||
|
||||
signing_key = SigningKey::generate(&mut csprng);
|
||||
good_sig = signing_key.sign(&good);
|
||||
|
Loading…
x
Reference in New Issue
Block a user