false-bottom 0.3.4

A deniable encryption scheme
Documentation
use crate::{FbError, FbKey, FbObj, PrimeField, Packing};
use crypto_bigint::{ArrayEncoding, NonZero, RandomMod, Uint};
use std::sync::RwLock;
use rayon::iter::*;

/// The main interface to the False Bottom algorithm.
pub trait FalseBottom {
	/// Creates a new `FbObj`.
	/// The keybase and ciphertext are initialized from random values.  
	/// Bounds: `2 <= keybase_len <= cipher_len`
	/// # Panics
	/// If Parameters are out of bounds.
	fn init(cipher_len: usize, keybase_len: usize) -> Self;

	/// Adds the provided message to the ciphertext.
	fn add(&mut self, msg: &[u8]) -> FbKey;

	/// Decrypts the message that corresponds to the provided key.
	/// # Errors
	/// [InvalidKey](FbError::InvalidKey)
	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(|index_row| self.add_block(&mut rand::thread_rng(), &index_row))
			.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)
	}
}