diff --git a/Cargo.toml b/Cargo.toml index f086a84..7203dc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,13 +23,13 @@ byteorder = "1.2.7" errno = "0.2.4" failure = "0.1.3" hex_fmt = "0.2.0" -init_with = "1.1.0" lazy_static = "1.1.0" log = "0.4.5" memsec = "0.5.4" pairing = { version = "0.14.2", features = ["u128-support"] } -rand = "0.4.3" -rand_derive = "0.3.1" +rand = "0.6.1" +rand04_compat = { git = "https://github.com/poanetwork/rand04_compat" } +rand_chacha = "0.1.0" serde = "1.0.80" serde_derive = "1.0.80" tiny-keccak = "1.4.2" @@ -37,8 +37,8 @@ tiny-keccak = "1.4.2" [dev-dependencies] bincode = "1.0.1" criterion = "0.2.5" -rand = "0.4.3" serde_derive = "1.0.80" +rand_xorshift = "0.1.0" [[bench]] name = "bench" diff --git a/benches/bench.rs b/benches/bench.rs index f042783..b576589 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -4,11 +4,13 @@ use threshold_crypto::Fr; const TEST_DEGREES: [usize; 4] = [5, 10, 20, 40]; const TEST_THRESHOLDS: [usize; 4] = [5, 10, 20, 40]; -const RNG_SEED: [u32; 4] = [1, 2, 3, 4]; +const RNG_SEED: [u8; 16] = *b"0123456789abcdef"; mod poly_benches { use super::*; - use rand::{Rng, SeedableRng, XorShiftRng}; + use rand::SeedableRng; + use rand04_compat::RngExt; + use rand_xorshift::XorShiftRng; /// Benchmarks multiplication of two polynomials. fn multiplication(c: &mut Criterion) { @@ -67,7 +69,8 @@ mod poly_benches { c.bench_function_over_inputs( "Polynomial interpolation", move |b, &°| { - let rand_samples = || (0..=deg).map(|i| (i, rng.gen::())).collect::>(); + let mut gen_tuple = |i: usize| (i, rng.gen04::()); + let rand_samples = move || (0..=deg).map(&mut gen_tuple).collect::>(); b.iter_with_setup(rand_samples, Poly::interpolate) }, &TEST_DEGREES, @@ -83,7 +86,8 @@ mod poly_benches { mod public_key_set_benches { use super::*; - use rand::{SeedableRng, XorShiftRng}; + use rand::SeedableRng; + use rand_xorshift::XorShiftRng; use std::collections::BTreeMap; use threshold_crypto::SecretKeySet; diff --git a/src/lib.rs b/src/lib.rs index a36a6de..637c2d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,13 +24,13 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::ptr::copy_nonoverlapping; -use byteorder::{BigEndian, ByteOrder}; use hex_fmt::HexFmt; -use init_with::InitWith; use log::debug; use pairing::{CurveAffine, CurveProjective, EncodedPoint, Engine, Field}; -use rand::{ChaChaRng, OsRng, Rand, Rng, SeedableRng}; -use rand_derive::Rand; +use rand::distributions::{Distribution, Standard}; +use rand::{rngs::OsRng, Rng, SeedableRng}; +use rand04_compat::RngExt; +use rand_chacha::ChaChaRng; use serde_derive::{Deserialize, Serialize}; use tiny_keccak::sha3_256; @@ -59,9 +59,6 @@ pub const PK_SIZE: usize = 48; #[cfg(not(feature = "use-insecure-test-only-mock-crypto"))] pub const SIG_SIZE: usize = 96; -/// The number of words (`u32`) in a ChaCha RNG seed. -const CHACHA_RNG_SEED_SIZE: usize = 8; - const ERR_OS_RNG: &str = "could not initialize the OS random number generator"; /// A public key. @@ -104,7 +101,7 @@ impl PublicKey { /// Encrypts the message. pub fn encrypt_with_rng>(&self, rng: &mut R, msg: M) -> Ciphertext { - let r: Fr = rng.gen(); + let r: Fr = rng.gen04(); let u = G1Affine::one().mul(r); let v: Vec = { let g = self.0.into_affine().mul(r); @@ -175,9 +172,15 @@ impl PublicKeyShare { /// A signature. // Note: Random signatures can be generated for testing. -#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Rand)] +#[derive(Deserialize, Serialize, Clone, PartialEq, Eq)] pub struct Signature(#[serde(with = "serde_impl::projective")] G2); +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> Signature { + Signature(rng.gen04()) + } +} + impl fmt::Debug for Signature { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let uncomp = self.0.into_affine().into_uncompressed(); @@ -220,9 +223,15 @@ impl Signature { /// A signature share. // Note: Random signature shares can be generated for testing. -#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Rand, Hash)] +#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash)] pub struct SignatureShare(pub Signature); +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> SignatureShare { + SignatureShare(rng.gen()) + } +} + impl fmt::Debug for SignatureShare { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let uncomp = (self.0).0.into_affine().into_uncompressed(); @@ -256,12 +265,9 @@ impl Default for SecretKey { } } -/// Creates a random `SecretKey` from a given RNG. If you do not need to specify your own RNG, you -/// should use `SecretKey::random()` as your constructor instead. -impl Rand for SecretKey { - fn rand(rng: &mut R) -> Self { - let mut fr = Fr::rand(rng); - SecretKey::from_mut(&mut fr) +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> SecretKey { + SecretKey(Box::new(rng.gen04())) } } @@ -318,8 +324,7 @@ impl SecretKey { /// [`rand::thead_rng()`](https://docs.rs/rand/0.4.3/rand/fn.thread_rng.html) internally as /// its RNG. pub fn random() -> Self { - let mut rng = rand::thread_rng(); - SecretKey::rand(&mut rng) + rand::random() } /// Returns the matching public key. @@ -359,9 +364,15 @@ impl SecretKey { } /// A secret key share. -#[derive(Clone, PartialEq, Eq, Rand, Default)] +#[derive(Clone, PartialEq, Eq, Default)] pub struct SecretKeyShare(SecretKey); +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> SecretKeyShare { + SecretKeyShare(rng.gen()) + } +} + impl fmt::Debug for SecretKeyShare { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("SecretKeyShare").field(&"...").finish() @@ -445,9 +456,15 @@ impl Ciphertext { } /// A decryption share. A threshold of decryption shares can be used to decrypt a message. -#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Rand)] +#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)] pub struct DecryptionShare(#[serde(with = "serde_impl::projective")] G1); +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> DecryptionShare { + DecryptionShare(rng.gen04()) + } +} + impl Hash for DecryptionShare { fn hash(&self, state: &mut H) { self.0.into_affine().into_compressed().as_ref().hash(state); @@ -577,11 +594,7 @@ impl SecretKeySet { /// Returns a hash of the given message in `G2`. pub fn hash_g2>(msg: M) -> G2 { let digest = sha3_256(msg.as_ref()); - let seed = <[u32; CHACHA_RNG_SEED_SIZE]>::init_with_indices(|i| { - BigEndian::read_u32(&digest.as_ref()[(4 * i)..(4 * i + 4)]) - }); - let mut rng = ChaChaRng::from_seed(&seed); - rng.gen() + ChaChaRng::from_seed(digest).gen04() } /// Returns a hash of the group element and message, in the second group. @@ -600,12 +613,9 @@ fn hash_g1_g2>(g1: G1, msg: M) -> G2 { /// Returns the bitwise xor of `bytes` with a sequence of pseudorandom bytes determined by `g1`. fn xor_with_hash(g1: G1, bytes: &[u8]) -> Vec { let digest = sha3_256(g1.into_affine().into_compressed().as_ref()); - let seed = <[u32; CHACHA_RNG_SEED_SIZE]>::init_with_indices(|i| { - BigEndian::read_u32(&digest.as_ref()[(4 * i)..(4 * i + 4)]) - }); - let mut rng = ChaChaRng::from_seed(&seed); + let mut rng = ChaChaRng::from_seed(digest); let xor = |(a, b): (u8, &u8)| a ^ b; - rng.gen_iter().zip(bytes).map(xor).collect() + rng.gen_iter04().zip(bytes).map(xor).collect() } use std::borrow::Borrow; @@ -674,7 +684,8 @@ mod tests { use std::collections::BTreeMap; - use rand::{self, random, Rng}; + use rand::{self, distributions::Standard, random, Rng}; + use rand04_compat::rand04::random as random04; #[test] fn test_interpolate() { @@ -828,7 +839,7 @@ mod tests { #[test] fn test_hash_g2() { let mut rng = rand::thread_rng(); - let msg: Vec = (0..1000).map(|_| rng.gen()).collect(); + let msg: Vec = rng.sample_iter(&Standard).take(1000).collect(); let msg_end0: Vec = msg.iter().chain(b"end0").cloned().collect(); let msg_end1: Vec = msg.iter().chain(b"end1").cloned().collect(); @@ -841,11 +852,11 @@ mod tests { #[test] fn test_hash_g1_g2() { let mut rng = rand::thread_rng(); - let msg: Vec = (0..1000).map(|_| rng.gen()).collect(); + let msg: Vec = rng.sample_iter(&Standard).take(1000).collect(); let msg_end0: Vec = msg.iter().chain(b"end0").cloned().collect(); let msg_end1: Vec = msg.iter().chain(b"end1").cloned().collect(); - let g0 = rng.gen(); - let g1 = rng.gen(); + let g0 = random04(); + let g1 = random04(); assert_eq!(hash_g1_g2(g0, &msg), hash_g1_g2(g0, &msg)); assert_ne!(hash_g1_g2(g0, &msg), hash_g1_g2(g0, &msg_end0)); @@ -856,9 +867,8 @@ mod tests { /// Some basic sanity checks for the `hash_bytes` function. #[test] fn test_xor_with_hash() { - let mut rng = rand::thread_rng(); - let g0 = rng.gen(); - let g1 = rng.gen(); + let g0 = random04(); + let g1 = random04(); let xwh = xor_with_hash; assert_eq!(xwh(g0, &[0; 5]), xwh(g0, &[0; 5])); assert_ne!(xwh(g0, &[0; 5]), xwh(g1, &[0; 5])); diff --git a/src/mock/mod.rs b/src/mock/mod.rs index 706c2d8..d73e0c4 100644 --- a/src/mock/mod.rs +++ b/src/mock/mod.rs @@ -15,7 +15,7 @@ pub mod ms8; use std::{fmt, mem, slice}; use pairing::{EncodedPoint, Field, GroupDecodingError, PrimeField}; -use rand; +use rand04_compat::rand04 as rand; use super::{CurveAffine, CurveProjective, Engine}; diff --git a/src/mock/ms8.rs b/src/mock/ms8.rs index 7c758d6..b8a832a 100644 --- a/src/mock/ms8.rs +++ b/src/mock/ms8.rs @@ -14,7 +14,7 @@ use byteorder::{BigEndian, ByteOrder}; use pairing::{ Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, }; -use rand; +use rand04_compat::rand04 as rand; /// Modular exponentiation /// diff --git a/src/poly.rs b/src/poly.rs index 0c55a75..2379dbc 100644 --- a/src/poly.rs +++ b/src/poly.rs @@ -24,6 +24,7 @@ use std::{cmp, iter, ops}; use pairing::{CurveAffine, CurveProjective, Field}; use rand::Rng; +use rand04_compat::RngExt; use serde_derive::{Deserialize, Serialize}; use crate::error::{Error, Result}; @@ -295,7 +296,7 @@ impl Poly { if degree == usize::max_value() { return Err(Error::DegreeTooHigh); } - let coeff: Vec = (0..=degree).map(|_| rng.gen()).collect(); + let coeff: Vec = rng.gen_iter04().take(degree + 1).collect(); Ok(Poly::from(coeff)) } @@ -566,7 +567,7 @@ impl BivarPoly { .ok_or(Error::DegreeTooHigh)?; let poly = BivarPoly { degree, - coeff: (0..len).map(|_| rng.gen()).collect(), + coeff: rng.gen_iter04().take(len).collect(), }; Ok(poly) } diff --git a/src/serde_impl.rs b/src/serde_impl.rs index d79c839..a617259 100644 --- a/src/serde_impl.rs +++ b/src/serde_impl.rs @@ -201,7 +201,8 @@ pub mod field_vec { #[cfg(test)] mod tests { use bincode; - use rand::{self, Rng}; + use rand; + use rand04_compat::RngExt; use serde_derive::{Deserialize, Serialize}; use crate::poly::BivarPoly; @@ -225,8 +226,8 @@ mod tests { fn vecs() { let mut rng = rand::thread_rng(); let vecs = Vecs { - curve_points: rng.gen_iter().take(10).collect(), - field_elements: rng.gen_iter().take(10).collect(), + curve_points: rng.gen_iter04().take(10).collect(), + field_elements: rng.gen_iter04().take(10).collect(), }; let ser_vecs = bincode::serialize(&vecs).expect("serialize vecs"); let de_vecs = bincode::deserialize(&ser_vecs).expect("deserialize vecs");