tfhe_csprng/seeders/
mod.rs1#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub struct Seed(pub u128);
11
12#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Versionize)]
20#[versionize(XofSeedVersions)]
21pub struct XofSeed {
22 data: Vec<u8>,
25}
26
27impl XofSeed {
28 pub const DOMAIN_SEP_LEN: usize = 8;
29
30 pub fn new_u128(seed: u128, domain_separator: [u8; Self::DOMAIN_SEP_LEN]) -> Self {
32 let mut data = vec![0u8; size_of::<u128>() + domain_separator.len()];
33 data[..Self::DOMAIN_SEP_LEN].copy_from_slice(domain_separator.as_slice());
34 data[Self::DOMAIN_SEP_LEN..].copy_from_slice(seed.to_le_bytes().as_slice());
35
36 Self { data }
37 }
38
39 pub fn new(mut seed: Vec<u8>, domain_separator: [u8; Self::DOMAIN_SEP_LEN]) -> Self {
40 seed.resize(domain_separator.len() + seed.len(), 0);
41 seed.rotate_right(domain_separator.len());
42 seed[..Self::DOMAIN_SEP_LEN].copy_from_slice(domain_separator.as_slice());
43 Self { data: seed }
44 }
45
46 pub fn seed(&self) -> &[u8] {
48 &self.data[Self::DOMAIN_SEP_LEN..]
49 }
50
51 pub fn domain_separator(&self) -> [u8; Self::DOMAIN_SEP_LEN] {
53 let mut sep = [0u8; Self::DOMAIN_SEP_LEN];
54 sep.copy_from_slice(&self.data[..Self::DOMAIN_SEP_LEN]);
55 sep
56 }
57
58 pub fn bit_len(&self) -> u128 {
60 (self.data.len()) as u128 * 8
61 }
62
63 pub(crate) fn iter_u128_blocks(&self) -> impl Iterator<Item = u128> + '_ {
66 self.data.chunks(size_of::<u128>()).map(move |chunk| {
67 let mut buf = [0u8; size_of::<u128>()];
68 buf[..chunk.len()].copy_from_slice(chunk);
69 u128::from_ne_bytes(buf)
70 })
71 }
72
73 pub fn from_bytes(data: Vec<u8>) -> Self {
79 assert!(
80 data.len() >= Self::DOMAIN_SEP_LEN,
81 "XofSeed must be at least {} bytes long (got {})",
82 Self::DOMAIN_SEP_LEN,
83 data.len()
84 );
85 Self { data }
86 }
87
88 pub fn bytes(&self) -> &Vec<u8> {
89 &self.data
90 }
91
92 pub fn into_bytes(self) -> Vec<u8> {
93 self.data
94 }
95}
96
97pub enum SeedKind {
98 Ctr(Seed),
101 Xof(XofSeed),
107}
108
109impl From<Seed> for SeedKind {
110 fn from(value: Seed) -> Self {
111 Self::Ctr(value)
112 }
113}
114
115impl From<XofSeed> for SeedKind {
116 fn from(value: XofSeed) -> Self {
117 Self::Xof(value)
118 }
119}
120
121pub trait Seeder {
123 fn seed(&mut self) -> Seed;
125
126 fn is_available() -> bool
129 where
130 Self: Sized;
131}
132
133pub mod backward_compatibility;
134mod implem;
135#[allow(unused_imports)]
138pub use implem::*;
139use tfhe_versionable::Versionize;
140
141use crate::seeders::backward_compatibility::XofSeedVersions;
142
143#[cfg(test)]
144mod generic_tests {
145 use crate::seeders::{Seeder, XofSeed};
146
147 #[allow(unused)] pub fn check_seeder_fixed_sequences_different<S: Seeder, F: Fn(u128) -> S>(
151 construct_seeder: F,
152 ) {
153 const SEQUENCE_SIZE: usize = 500;
154 const REPEATS: usize = 10_000;
155 for i in 0..REPEATS {
156 let mut seeder = construct_seeder(i as u128);
157 let orig_seed = seeder.seed();
158 for _ in 0..SEQUENCE_SIZE {
159 assert_ne!(seeder.seed(), orig_seed);
160 }
161 }
162 }
163
164 #[test]
165 fn test_xof_seed_getters() {
166 let seed_bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
167 let bits = u128::from_le_bytes(seed_bytes);
168 let dsep = [b't', b'f', b'h', b'e', b'k', b's', b'p', b's'];
169 let seed = XofSeed::new_u128(bits, dsep);
170
171 let s = u128::from_le_bytes(seed.seed().try_into().unwrap());
172 assert_eq!(s, bits);
173 assert_eq!(seed.domain_separator(), dsep);
174 assert_eq!(seed.bit_len(), 192);
175
176 let collected_u128s = seed.iter_u128_blocks().collect::<Vec<_>>();
177 assert_eq!(
180 collected_u128s,
181 vec![
182 u128::from_ne_bytes([
183 b't', b'f', b'h', b'e', b'k', b's', b'p', b's', 1, 2, 3, 4, 5, 6, 7, 8
184 ]),
185 u128::from_ne_bytes([9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0]),
186 ]
187 );
188
189 let seed2 = XofSeed::new(seed_bytes.to_vec(), dsep);
191 assert_eq!(seed.data, seed2.data);
192 }
193}