#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Versionize)]
#[versionize(SeedVersions)]
pub struct Seed(pub u128);
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Versionize)]
#[versionize(XofSeedVersions)]
pub struct XofSeed {
data: Vec<u8>,
}
impl XofSeed {
pub const DOMAIN_SEP_LEN: usize = 8;
pub fn new_u128(seed: u128, domain_separator: [u8; Self::DOMAIN_SEP_LEN]) -> Self {
let mut data = vec![0u8; size_of::<u128>() + domain_separator.len()];
data[..Self::DOMAIN_SEP_LEN].copy_from_slice(domain_separator.as_slice());
data[Self::DOMAIN_SEP_LEN..].copy_from_slice(seed.to_le_bytes().as_slice());
Self { data }
}
pub fn new(mut seed: Vec<u8>, domain_separator: [u8; Self::DOMAIN_SEP_LEN]) -> Self {
seed.resize(domain_separator.len() + seed.len(), 0);
seed.rotate_right(domain_separator.len());
seed[..Self::DOMAIN_SEP_LEN].copy_from_slice(domain_separator.as_slice());
Self { data: seed }
}
pub fn seed(&self) -> &[u8] {
&self.data[Self::DOMAIN_SEP_LEN..]
}
pub fn domain_separator(&self) -> [u8; Self::DOMAIN_SEP_LEN] {
let mut sep = [0u8; Self::DOMAIN_SEP_LEN];
sep.copy_from_slice(&self.data[..Self::DOMAIN_SEP_LEN]);
sep
}
pub fn bit_len(&self) -> u128 {
(self.data.len()) as u128 * 8
}
pub(crate) fn iter_u128_blocks(&self) -> impl Iterator<Item = u128> + '_ {
self.data.chunks(size_of::<u128>()).map(move |chunk| {
let mut buf = [0u8; size_of::<u128>()];
buf[..chunk.len()].copy_from_slice(chunk);
u128::from_ne_bytes(buf)
})
}
pub fn from_bytes(data: Vec<u8>) -> Self {
assert!(
data.len() >= Self::DOMAIN_SEP_LEN,
"XofSeed must be at least {} bytes long (got {})",
Self::DOMAIN_SEP_LEN,
data.len()
);
Self { data }
}
pub fn bytes(&self) -> &Vec<u8> {
&self.data
}
pub fn into_bytes(self) -> Vec<u8> {
self.data
}
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(SeedKindVersions)]
pub enum SeedKind {
Ctr(Seed),
Xof(XofSeed),
}
impl From<Seed> for SeedKind {
fn from(value: Seed) -> Self {
Self::Ctr(value)
}
}
impl From<XofSeed> for SeedKind {
fn from(value: XofSeed) -> Self {
Self::Xof(value)
}
}
pub trait Seeder {
fn seed(&mut self) -> Seed;
fn is_available() -> bool
where
Self: Sized;
}
pub mod backward_compatibility;
mod implem;
#[allow(unused_imports)]
pub use implem::*;
use tfhe_versionable::Versionize;
use crate::seeders::backward_compatibility::{SeedKindVersions, SeedVersions, XofSeedVersions};
#[cfg(test)]
mod generic_tests {
use crate::seeders::{Seeder, XofSeed};
#[allow(unused)] pub fn check_seeder_fixed_sequences_different<S: Seeder, F: Fn(u128) -> S>(
construct_seeder: F,
) {
const SEQUENCE_SIZE: usize = 500;
const REPEATS: usize = 10_000;
for i in 0..REPEATS {
let mut seeder = construct_seeder(i as u128);
let orig_seed = seeder.seed();
for _ in 0..SEQUENCE_SIZE {
assert_ne!(seeder.seed(), orig_seed);
}
}
}
#[test]
fn test_xof_seed_getters() {
let seed_bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let bits = u128::from_le_bytes(seed_bytes);
let dsep = [b't', b'f', b'h', b'e', b'k', b's', b'p', b's'];
let seed = XofSeed::new_u128(bits, dsep);
let s = u128::from_le_bytes(seed.seed().try_into().unwrap());
assert_eq!(s, bits);
assert_eq!(seed.domain_separator(), dsep);
assert_eq!(seed.bit_len(), 192);
let collected_u128s = seed.iter_u128_blocks().collect::<Vec<_>>();
assert_eq!(
collected_u128s,
vec![
u128::from_ne_bytes([
b't', b'f', b'h', b'e', b'k', b's', b'p', b's', 1, 2, 3, 4, 5, 6, 7, 8
]),
u128::from_ne_bytes([9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0]),
]
);
let seed2 = XofSeed::new(seed_bytes.to_vec(), dsep);
assert_eq!(seed.data, seed2.data);
}
}