1use core::fmt::{self, Debug, Formatter};
4
5use aead::generic_array::{typenum::Unsigned, GenericArray};
6use chacha20::{
7 cipher::{KeyIvInit, KeySizeUser, StreamCipher},
8 ChaCha20,
9};
10use rand::{CryptoRng, RngCore, SeedableRng};
11
12#[cfg(all(feature = "alloc", feature = "getrandom"))]
13use crate::buffer::SecretBytes;
14use crate::error::Error;
15
16pub const DETERMINISTIC_SEED_LENGTH: usize = <ChaCha20 as KeySizeUser>::KeySize::USIZE;
18
19pub trait Rng: CryptoRng + RngCore + Debug {}
21
22impl<T: CryptoRng + RngCore + Debug> Rng for T {}
23
24pub trait KeyMaterial {
27 fn read_okm(&mut self, buf: &mut [u8]);
29}
30
31impl<C: CryptoRng + RngCore> KeyMaterial for C {
32 fn read_okm(&mut self, buf: &mut [u8]) {
33 self.fill_bytes(buf);
34 }
35}
36
37#[cfg(feature = "getrandom")]
38#[cfg_attr(docsrs, doc(cfg(feature = "getrandom")))]
39#[inline]
40pub fn default_rng() -> impl CryptoRng + RngCore + Debug + Clone {
42 #[cfg(feature = "std_rng")]
43 {
44 rand::rngs::ThreadRng::default()
45 }
46 #[cfg(not(feature = "std_rng"))]
47 {
48 rand::rngs::OsRng
49 }
50}
51
52#[cfg(feature = "getrandom")]
55#[inline(always)]
56pub fn fill_random(value: &mut [u8]) {
57 default_rng().fill_bytes(value);
58}
59
60pub fn fill_random_deterministic(seed: &[u8], output: &mut [u8]) -> Result<(), Error> {
63 RandomDet::new(seed).fill_bytes(output);
64 Ok(())
65}
66
67pub struct RandomDet {
69 cipher: ChaCha20,
70}
71
72impl Debug for RandomDet {
73 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74 write!(f, "RandomDet {{}}")
75 }
76}
77
78impl SeedableRng for RandomDet {
79 type Seed = [u8; DETERMINISTIC_SEED_LENGTH];
80
81 #[inline]
82 fn from_seed(seed: Self::Seed) -> Self {
83 Self {
84 cipher: ChaCha20::new(
85 GenericArray::from_slice(&seed[..]),
86 GenericArray::from_slice(b"LibsodiumDRG"),
87 ),
88 }
89 }
90}
91
92impl CryptoRng for RandomDet {}
93
94impl RngCore for RandomDet {
95 #[inline]
96 fn next_u32(&mut self) -> u32 {
97 let mut buf = [0; 4];
98 self.cipher.apply_keystream(&mut buf[..]);
99 u32::from_le_bytes(buf)
100 }
101
102 #[inline]
103 fn next_u64(&mut self) -> u64 {
104 let mut buf = [0; 8];
105 self.cipher.apply_keystream(&mut buf[..]);
106 u64::from_le_bytes(buf)
107 }
108
109 #[inline]
110 fn fill_bytes(&mut self, bytes: &mut [u8]) {
111 bytes.iter_mut().for_each(|b| *b = 0u8);
112 self.cipher.apply_keystream(bytes);
113 }
114
115 #[inline]
116 fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), rand::Error> {
117 bytes.iter_mut().for_each(|b| *b = 0u8);
118 self.cipher.apply_keystream(bytes);
119 Ok(())
120 }
121}
122
123impl RandomDet {
124 pub fn new(seed: &[u8]) -> Self {
126 let mut sd = [0u8; DETERMINISTIC_SEED_LENGTH];
127 let seed_len = seed.len().min(DETERMINISTIC_SEED_LENGTH);
128 sd[..seed_len].copy_from_slice(&seed[..seed_len]);
129 Self::from_seed(sd)
130 }
131}
132
133#[cfg(all(feature = "alloc", feature = "getrandom"))]
134#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
135#[inline(always)]
137pub fn random_secret(len: usize) -> SecretBytes {
138 SecretBytes::new_with(len, fill_random)
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use crate::buffer::HexRepr;
145 use std::string::ToString;
146
147 #[test]
148 fn fill_random_det_expected() {
149 let seed = b"testseed000000000000000000000001";
150 let mut output = [0u8; 32];
151 fill_random_deterministic(seed, &mut output).unwrap();
152 assert_eq!(
153 HexRepr(output).to_string(),
154 "b1923a011cd1adbe89552db9862470c29512a8f51d184dfd778bfe7f845390d1"
155 );
156 }
157}