use std::io::{Read, Write};
use core::cmp::Ordering;
use num_bigint::BigInt;
use num_bigint_dig as num_bigint;
use rand::{rngs::StdRng, RngCore, SeedableRng};
use sha2::{Digest, Sha256};
use crate::{
cipher::{stream::Stream, StreamError},
xof::blake3::Xof,
};
pub fn bits(bit_len: u64, exact: bool, rand: &mut impl Stream) -> Vec<u8> {
let mut b: Vec<u8> = vec![0; ((bit_len + 7) / 8) as usize];
let b_clone = b.clone();
_ = rand.xor_key_stream(&mut b, &b_clone);
let highbits = bit_len & 7;
if highbits != 0 {
b[0] &= !(0xff << highbits);
}
if exact {
if highbits != 0 {
b[0] |= 1 << (highbits - 1)
} else {
b[0] |= 0x80
}
}
b
}
pub fn random_int(modulus: &BigInt, rand: &mut impl Stream) -> BigInt {
let bitlen = modulus.bits();
loop {
let bits = bits(bitlen as u64, false, rand);
let i = BigInt::from_bytes_be(num_bigint::Sign::Plus, bits.as_ref());
if i.sign() == num_bigint::Sign::Plus && i.cmp(modulus) == Ordering::Less {
return i;
}
}
}
pub fn bytes(b: &mut [u8], rand: &mut impl Stream) -> Result<(), StreamError> {
let src_buff = vec![0u8; b.len()];
rand.xor_key_stream(b, &src_buff)?;
Ok(())
}
pub struct RandStream {
readers: Vec<Box<dyn Read>>,
}
impl Default for RandStream {
fn default() -> Self {
let rng_core = Box::new(StdRng::from_entropy()) as Box<dyn RngCore>;
let default: Box<dyn Read> = Box::new(rng_core) as Box<dyn Read>;
RandStream {
readers: vec![default],
}
}
}
impl RandStream {
pub fn new(readers: Vec<Box<dyn Read>>) -> RandStream {
if readers.is_empty() {
return RandStream::default();
}
RandStream {
readers: readers
.into_iter()
.map(|r| Box::new(r) as Box<dyn Read>)
.collect(),
}
}
}
impl Stream for RandStream {
fn xor_key_stream(&mut self, dst: &mut [u8], src: &[u8]) -> Result<(), StreamError> {
let l = dst.len();
if src.len() != l {
return Err(StreamError::WrongBufferLengths);
}
let reader_bytes = 32;
let mut b = vec![];
let mut nerr = 0_usize;
let mut buff = vec![0_u8; reader_bytes];
for reader in &mut self.readers {
let result = reader.read_exact(&mut buff);
if result.is_err() {
nerr += 1;
continue;
}
b.write_all(&buff[..buff.len()])?;
}
if nerr == self.readers.len() {
return Err(StreamError::ReadersFailure);
}
let mut h: Sha256 = Sha256::new();
h.update(b);
let seed = h.finalize();
let mut blake = Xof::new(Some(&seed));
blake.xor_key_stream(dst, src)
}
}