diff --git a/src/proof.rs b/src/proof.rs index 9acb59c..5a343f5 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -18,7 +18,7 @@ use snafu::prelude::*; use subtle::{ConditionallySelectable, ConstantTimeEq}; use zeroize::Zeroizing; -use crate::{gray::GrayIterator, statement::Statement, util::DangerousRng, witness::Witness}; +use crate::{gray::GrayIterator, statement::Statement, util::NullRng, witness::Witness}; // Proof version flag const VERSION: u64 = 0; @@ -514,13 +514,13 @@ impl Proof { transcript.append_message("z_A".as_bytes(), proof.z_A.as_bytes()); transcript.append_message("z_C".as_bytes(), proof.z_C.as_bytes()); transcript.append_message("z".as_bytes(), proof.z.as_bytes()); - let mut transcript_rng = transcript.build_rng().finalize(&mut DangerousRng); + let mut transcript_rng = transcript.build_rng().finalize(&mut NullRng); transcript_weights.append_u64("proof".as_bytes(), transcript_rng.as_rngcore().next_u64()); } // Finalize the weighting transcript into a pseudorandom number generator - let mut transcript_weights_rng = transcript_weights.build_rng().finalize(&mut DangerousRng); + let mut transcript_weights_rng = transcript_weights.build_rng().finalize(&mut NullRng); // Process each proof for (proof, xi_powers) in proofs.iter().zip(xi_powers_all.iter()) { diff --git a/src/util.rs b/src/util.rs index d5a3227..015a96d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -5,11 +5,12 @@ use rand_core::{ }; use zeroize::Zeroize; -/// A "null" random number generator that exists only for deterministic transcript-based weight generation. +/// A null random number generator that exists only for deterministic transcript-based weight generation. +/// It only produces zero. /// This is DANGEROUS in general, and you almost certainly should not use it elsewhere! -pub(crate) struct DangerousRng; +pub(crate) struct NullRng; -impl RngCore for DangerousRng { +impl RngCore for NullRng { #[allow(unused_variables)] fn fill_bytes(&mut self, dest: &mut [u8]) { dest.zeroize(); @@ -31,4 +32,31 @@ impl RngCore for DangerousRng { } } -impl CryptoRng for DangerousRng {} +impl CryptoRng for NullRng {} + +#[cfg(test)] +mod test { + use rand_core::RngCore; + + use super::NullRng; + + #[test] + fn test_null_rng() { + // Ensure that the null RNG supplies only zero + let mut rng = NullRng; + + assert_eq!(rng.next_u32(), 0); + assert_eq!(rng.next_u64(), 0); + + // Ensure that buffers are filled with only zero + const BUFFER_SIZE: usize = 128; + + let mut buffer = [1u8; BUFFER_SIZE]; // start with nonzero + rng.fill_bytes(&mut buffer); + assert_eq!(buffer, [0u8; BUFFER_SIZE]); + + let mut buffer = [1u8; BUFFER_SIZE]; // start with nonzero + rng.try_fill_bytes(&mut buffer).unwrap(); + assert_eq!(buffer, [0u8; BUFFER_SIZE]); + } +}