pub use rand_core::{CryptoRngCore, OsRng, RngCore};
use crate::error::Result;
#[cfg(any(feature = "ecies", feature = "transport-cms"))]
use rand_core::CryptoRng;
#[cfg(any(feature = "ecies", feature = "transport-cms"))]
pub(crate) struct RngWrapper<'a>(pub(crate) &'a mut dyn CryptoRngCore);
#[cfg(any(feature = "ecies", feature = "transport-cms"))]
impl RngCore for RngWrapper<'_> {
fn next_u32(&mut self) -> u32 {
self.0.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.0.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0.fill_bytes(dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
self.0.try_fill_bytes(dest)
}
}
#[cfg(any(feature = "ecies", feature = "transport-cms"))]
impl CryptoRng for RngWrapper<'_> {}
#[inline]
pub fn generate_nonce<const N: usize>(rng: Option<&mut dyn CryptoRngCore>) -> Result<[u8; N]> {
let mut nonce = [0u8; N];
let rng = if let Some(rng) = rng {
rng
} else {
&mut rand_core::OsRng
};
rng.fill_bytes(&mut nonce);
Ok(nonce)
}
pub fn generate_random_number<const N: usize>(rng: Option<&mut dyn RngCore>) -> Result<usize> {
const USIZE_BYTES: usize = core::mem::size_of::<usize>();
if N > USIZE_BYTES {
return Err(crate::TightBeamError::InvalidOverflowValue);
}
let mut bytes = [0u8; USIZE_BYTES];
generate_random_bytes(&mut bytes[..N], rng)?;
Ok(usize::from_le_bytes(bytes))
}
#[inline]
pub fn generate_random_bytes(bytes: &mut [u8], rng: Option<&mut dyn RngCore>) -> Result<()> {
let rng = if let Some(rng) = rng {
rng
} else {
&mut rand_core::OsRng
};
rng.fill_bytes(bytes);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_random() -> Result<()> {
#[allow(clippy::type_complexity)]
let cases: &[(usize, fn(&mut rand_core::OsRng) -> Result<(Vec<u8>, Vec<u8>)>)] = &[
(8, |rng| {
let n1 = generate_random_number::<8>(Some(rng))?;
let n2 = generate_random_number::<8>(None)?;
Ok((n1.to_be_bytes().to_vec(), n2.to_be_bytes().to_vec()))
}),
(16, |rng| {
let n1 = generate_nonce::<16>(Some(rng))?;
let n2 = generate_nonce::<16>(None)?;
Ok((n1.to_vec(), n2.to_vec()))
}),
(24, |rng| {
let mut n1 = [0u8; 24];
generate_random_bytes(&mut n1, Some(rng))?;
let mut n2 = [0u8; 24];
generate_random_bytes(&mut n2, None)?;
Ok((n1.to_vec(), n2.to_vec()))
}),
];
for &(size, gen) in cases {
let mut rng = rand_core::OsRng;
let (nonce1, nonce2) = gen(&mut rng)?;
assert_eq!(nonce1.len(), size);
assert_eq!(nonce2.len(), size);
assert_ne!(nonce1, nonce2);
assert_ne!(nonce1, vec![0u8; size]);
assert_ne!(nonce2, vec![0u8; size]);
}
Ok(())
}
}