#[cfg(feature = "random")]
use lib_q_random::Result;
#[cfg(feature = "random")]
use lib_q_random::traits::{
EntropySource,
EntropySourceType,
};
#[cfg(feature = "random")]
pub struct Shake256PrngEntropySource {
xof: crate::internal::shake256::Shake256Xof,
quality: f64,
}
#[cfg(feature = "random")]
impl Shake256PrngEntropySource {
pub fn new(entropy_input: [u8; 48]) -> Self {
let mut xof = crate::internal::shake256::Shake256Xof::new();
xof.absorb(&entropy_input)
.expect("SHAKE256 absorb entropy failed");
xof.absorb(&[])
.expect("SHAKE256 absorb personalization failed");
const HQC_PRNG_DOMAIN: u8 = 0; xof.absorb(&[HQC_PRNG_DOMAIN])
.expect("SHAKE256 absorb domain failed");
xof.finalize_absorb()
.expect("SHAKE256 finalize absorb failed");
Self {
xof,
quality: 0.95, }
}
}
#[cfg(feature = "random")]
impl EntropySource for Shake256PrngEntropySource {
fn get_entropy(&mut self, dest: &mut [u8]) -> Result<()> {
self.xof
.squeeze(dest)
.map_err(|_| lib_q_random::Error::entropy_source_unavailable("SHAKE256 squeeze failed"))
}
fn is_available(&self) -> bool {
true
}
fn quality(&self) -> f64 {
self.quality
}
fn name(&self) -> &'static str {
"SHAKE256 PRNG"
}
fn source_type(&self) -> EntropySourceType {
EntropySourceType::Deterministic
}
fn max_entropy_per_call(&self) -> Option<usize> {
None }
}
#[cfg(feature = "random")]
pub fn create_shake256_prng_rng(entropy_input: [u8; 48]) -> lib_q_random::LibQRng {
let entropy_source = Shake256PrngEntropySource::new(entropy_input);
lib_q_random::LibQRng::new_custom(entropy_source)
}