-
Notifications
You must be signed in to change notification settings - Fork 783
Description
One of the latest update to ring (v0.13.0-alpha5) broke some code we use for a mock deterministic random generator. We use it for testing. This is what it looks like:
use std::cell::RefCell;
use rand::{self, Rng, StdRng};
use ring::{error::Unspecified, rand::SecureRandom};
pub struct DummyRandom<R> {
rng: RefCell<R>,
}
impl DummyRandom<StdRng> {
pub fn new(seed: &[usize]) -> Self {
let rng_seed: &[_] = seed;
let rng: StdRng = rand::SeedableRng::from_seed(rng_seed);
// Note: We use UnsafeCell here, because of the signature of the function fill.
// It takes &self, it means that we can not change internal state with safe rust.
DummyRandom {
rng: RefCell::new(rng),
}
}
}
impl<R: Rng> SecureRandom for DummyRandom<R> {
fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
self.rng.borrow_mut().fill_bytes(dest);
Ok(())
}
}The compilation error I get is:
error[E0277]: the trait bound `crypto::test_utils::DummyRandom<R>: ring::private::Sealed` is not satisfied
--> src/crypto/test_utils.rs:23:14
|
23 | impl<R: Rng> SecureRandom for DummyRandom<R> {
| ^^^^^^^^^^^^ the trait `ring::private::Sealed` is not implemented for `crypto::test_utils::DummyRandom<R>`I assume that a new ring::private::Sealed trait was introduced for safety reasons, to make sure exactly that I don't do something like the code above. Having the ability to generate deterministic random is very important for my tests, because I would like the tests to be reproducible if something goes wrong. I don't want to have a test that sometimes succeeds and sometimes fails.
Here is some part from a test case where I used DummyRandom:
use super::super::test_utils::DummyRandom;
#[test]
fn test_rand_values_store() {
let rng = DummyRandom::new(&[1, 2, 3, 4, 5]);
// Generate some unrelated rand value:
let rand_value0 = RandValue::new(&rng);
let mut rand_values_store = RandValuesStore::new(&rng, 50, 5);
let rand_value = rand_values_store.last_rand_value();
// ...Now the options I am left with are to use one of:
- FixedByteRandom: A mock random generator that always returns the same byte. It is not very random looking.
- FixedSliceRandom: I have to prepare a slice of random
- FixedSliceSequenceRandom: I have to prepare a sequence of slices of random ahead of time.
In some test cases I am not sure exactly how much random will be requested from the random generator. I also don't think that I should deal with this. I would like to have a random generator that is deterministic and I can just plug into my tests, without serious preparation.
I understand the safety considerations and reasons for adding ring::private::Sealed. Could we have something like DummyRandom above as a workaround? I can make a pull request for this with my current implementation.
If this is not possible, what would be a good workaround?