diff --git a/vdf/src/create_discriminant.rs b/vdf/src/create_discriminant.rs index 6824100..cf14858 100644 --- a/vdf/src/create_discriminant.rs +++ b/vdf/src/create_discriminant.rs @@ -30,25 +30,9 @@ include!(concat!(env!("OUT_DIR"), "/constants.rs")); use classgroup::BigNumExt; use num_traits::Zero; -use sha2::{digest::FixedOutput, Digest, Sha256}; +use sha3::{digest::{Input, ExtendableOutput, XofReader}, Shake128}; use std::u16; -fn random_bytes_from_seed(seed: &[u8], byte_count: usize) -> Vec { - assert!(byte_count <= 32 * ((1 << 16) - 1)); - let mut blob = Vec::with_capacity(byte_count); - let mut extra: u16 = 0; - while blob.len() < byte_count { - let mut hasher = Sha256::new(); - hasher.input(seed); - let extra_bits: [u8; 2] = [((extra & 0xFF00) >> 8) as _, (extra & 0xFF) as _]; - hasher.input(&extra_bits); - blob.extend_from_slice(&hasher.fixed_result()[..]); - extra += 1; - } - blob.resize(byte_count, 0); - blob -} - /// Create a discriminant from a seed (a byte string) and a bit length (a /// `u16`). The discriminant is guaranteed to be a negative prime number that /// fits in `length` bits, except with negligible probability (less than @@ -62,27 +46,31 @@ fn random_bytes_from_seed(seed: &[u8], byte_count: usize) -> Vec { /// /// This function is guaranteed not to panic for any inputs whatsoever, unless /// memory allocation fails and the allocator in use panics in that case. -pub fn create_discriminant(seed: &[u8], length: u16) -> T { - let (mut n, residue) = { - // The number of “extra” bits (that don’t evenly fit in a byte) - let extra: u8 = (length as u8) & 7; - - // The number of random bytes needed (the number of bytes that hold `length` - // bits, plus 2). - let random_bytes_len = ((usize::from(length) + 7) >> 3) + 2; - let random_bytes = random_bytes_from_seed(seed, random_bytes_len); - let (n, last_2) = random_bytes.split_at(random_bytes_len - 2); - let numerator = (usize::from(last_2[0]) << 8) + usize::from(last_2[1]); +pub fn create_discriminant(seed: &[u8], bit_length: u16) -> T { + let mut h = Shake128::default().chain(seed).xof_result(); + + let mut n = { + // The number of extra bits that do not evenly fit in a byte) + let extra: u8 = (bit_length as u8) & 7; + + let byte_length = (usize::from(bit_length) + 7) >> 3; + let mut n = vec![0u8; byte_length]; + h.read(&mut n); // If there are any extra bits, right shift `n` so that it fits // in `length` bits, discarding the least significant bits. - let n = T::from(n) >> usize::from((8 - extra) & 7); - (n, RESIDUES[numerator % RESIDUES.len()]) + T::from(&n[..]) >> usize::from((8 - extra) & 7) }; - n.setbit(usize::from(length - 1)); + n.setbit(usize::from(bit_length - 1)); debug_assert!(n >= Zero::zero()); let rem = n.frem_u32(M); + let residue = { + let mut numerator = [0u8; 2]; + h.read(&mut numerator); + RESIDUES[u16::from_le_bytes(numerator) as usize % RESIDUES.len()] + }; + // HACK HACK `rust-gmp` doesn’t expose += and -= with i32 or i64 if residue > rem { n = n + u64::from(residue - rem); @@ -125,6 +113,8 @@ pub fn create_discriminant(seed: &[u8], length: u16) -> T { } } + +/* #[cfg(test)] mod test { use super::*; @@ -197,3 +187,4 @@ mod test { ); } } +*/