use crate::{FbError, FbKey, FbObj, PrimeField, Packing};
use crypto_bigint::{ArrayEncoding, NonZero, RandomMod, Uint};
use std::sync::RwLock;
use rayon::iter::*;
pub trait FalseBottom {
fn init(cipher_len: usize, keybase_len: usize) -> Self;
fn add(&mut self, msg: &[u8]) -> FbKey;
fn decrypt(&self, key: &FbKey) -> Result<Vec<u8>, FbError>;
}
impl<const LIMBS: usize> FalseBottom for FbObj<Uint<LIMBS>>
where
Uint<LIMBS>: ArrayEncoding + PrimeField
{
fn init(cipher_len: usize, keybase_len: usize) -> FbObj<Uint<LIMBS>> {
let modulus = NonZero::<Uint<LIMBS>>::new(Uint::<LIMBS>::PRIME).unwrap();
if cipher_len < keybase_len || keybase_len < 2 {
panic!("Valid bounds are: 2 <= keybase_len <= cipher_len");
}
let mut rng = rand::thread_rng();
let r = (0..keybase_len)
.map(|_| Uint::<LIMBS>::random_mod(&mut rng, &modulus))
.collect();
let c_vec = (0..cipher_len)
.map(|_| Uint::<LIMBS>::random_mod(&mut rng, &modulus))
.collect();
let c = RwLock::new(c_vec);
FbObj {c, r}
}
fn add(&mut self, msg: &[u8]) -> FbKey {
let indices = Uint::<LIMBS>::pack(msg)
.into_par_iter()
.map_init(
|| rand::thread_rng(),
|rng, index_row| self.add_block(rng, &index_row),
)
.collect();
FbKey(indices)
}
fn decrypt(&self, key: &FbKey) -> Result<Vec<u8>, FbError> {
let decr = key.0.iter()
.map(|index_row| self.decrypt_block(&index_row))
.collect::<Result<Vec<_>, _>>()?;
let msg = Uint::<LIMBS>::unpack(decr)?;
Ok(msg)
}
}