briansmith / ring

Safe, fast, small crypto using Rust
Other
3.75k stars 704 forks source link

Provide an easier-to-use rand API #728

Open briansmith opened 5 years ago

briansmith commented 5 years ago

Consider adding a function like this to ring::rand.

pub fn value<T: Default + AsMut<[u8]>>(rng: &SecureRandom) -> Result<T, error::Unspecified> {
    let mut r: T = Default::default();
    rng.fill(r.as_mut())?;
    Ok(r)
}

Then we could initialize fields like this:

struct Key {
   value: [u8; KEY_LENGTH],
}

impl Key {
    fn new(rng: &rand::SecureRandom) -> Result<Self, error::Unspecified> {
        Self { value: rand::value(rng) }
    }
}

Ideally rand::value() would work for arrays of all primitive integer types (usize, u128, u64, u32, u16, u8) and vector types. Thus we'd need to replace the AsMut<[u8]> bound with a more general one that admits those types.

sconybeare commented 5 years ago

I decided to take a stab at this. I haven't tried to make anything work for vectors, but I've implemented this with a trait bound that allows for the construction of primitive integer types, as well as fixed sized arrays thereof. The lengths of those arrays are arbitrarily limited to 32 elements because we don't have support for generic compile-time integers, and because I had to pick a number.

briansmith commented 5 years ago

In the interim, until we get this all sorted out, I created a new function:

pub fn generate<T: RandomlyConstructable>(
    rng: &SecureRandom,
) -> Result<Random<T>, error::Unspecified> { ... }

I implemented RandomlyConstructable for u8 arrays of lengths 4, 8, 16, 32, 48, and 64, since those are the lengths I know to be useful for ring users.

Notably, I was able to do so without using any unsafe. I think that's something we should strive for in a more generic implementation.

The lengths of those arrays are arbitrarily limited to 32 elements because we don't have support for generic compile-time integers, and because I had to pick a number.

[u8; 64] and [u8; 48] are commonly needed. In my implementation I avoid using the standard library's AsRef/AsMut implementations for this reason.