1use rand_core::{CryptoRng, OsRng, RngCore, SeedableRng as _};
2
3pub fn os_rng_hkdf(
5 nonce: Option<&[u8]>,
6 context: &[u8],
7) -> Result<impl RngCore + CryptoRng, hkdf::InvalidLength> {
8 let mut ikm = [0u8; 32];
9 OsRng.fill_bytes(&mut ikm);
10
11 let hk = hkdf::Hkdf::<sha2::Sha256>::new(nonce, &ikm);
12
13 let mut seed = [0u8; 32];
14 hk.expand(context, &mut seed)?;
15
16 Ok(rand_chacha::ChaCha20Rng::from_seed(seed))
17}
18
19#[cfg(test)]
20mod tests {
21 use super::*;
22
23 #[test]
24 fn test_os_rng_hkdf() {
25 let mut rng1 = os_rng_hkdf(None, b"test-context").unwrap();
26 let mut rng2 = os_rng_hkdf(Some(b"hey there!"), b"test-context").unwrap();
27
28 let mut buf1 = [0u8; 256];
29 let mut buf2 = [0u8; 256];
30
31 rng1.fill_bytes(&mut buf1);
32 rng2.fill_bytes(&mut buf2);
33
34 assert_ne!(buf1, buf2);
36 }
37}