WIP: Threading done

This commit is contained in:
K Shiva Kiran 2024-04-11 20:23:26 +05:30
parent 1eca9a6aa0
commit 888c863628
9 changed files with 87 additions and 39 deletions

View File

@ -14,6 +14,7 @@ crypto-bigint = {version = "0.5.5", features = ["generic-array"]}
base64 = "0.21.7"
bincode = "1.3.3"
typenum = "1.17.0"
rayon = "1.10.0"
[lib]
doctest = false

View File

@ -2,13 +2,13 @@ use false_bottom::{FB128, FBKey, FBAlgo, Encode};
fn main() {
// Cipher Initialization
let mut fb = FB128::init(18, 9).unwrap();
let mut fb = FB128::init(2, 2).unwrap();
// Encryption
let msg1 = "This is a message";
let key1 = fb.add(msg1.as_bytes());
let msg2 = "This is another message";
let key2 = fb.add(msg2.as_bytes());
let msg1 = "This is a message".as_bytes();
let key1 = fb.add(msg1);
let msg2 = "This is another message".as_bytes();
let key2 = fb.add(msg2);
// Export as base64
let (cipher, keybase) = fb.export(); // Careful with the order
@ -16,6 +16,14 @@ fn main() {
// Or as raw bytes
let key2_exp = key2.to_bytes();
let inp_len = msg1.len() + msg2.len();
let out_len = fb.to_bytes().0.len();
let extra = out_len - inp_len;
let percent = extra as f32/out_len as f32 * 100_f32;
println!("Input: {inp_len}B \nOutput: {out_len}B");
println!("Extra: {extra}B ({percent}%)");
// Import from base64
let fb_new = FB128::import(&cipher, &keybase).unwrap();
let key1_imp = FBKey::import(&key1_exp).unwrap();
@ -34,6 +42,6 @@ Key 1: {key1_exp}
Key 2: {key2_exp:?}
");
assert_eq!(msg1.as_bytes(), decr1);
assert_eq!(msg2.as_bytes(), decr2);
assert_eq!(msg1, decr1);
assert_eq!(msg2, decr2);
}

23
examples/file.rs Normal file
View File

@ -0,0 +1,23 @@
use false_bottom::{FB128, FBAlgo, Encode};
use std::fs;
use std::time::Instant;
fn main() {
//let inp = fs::read("input1").unwrap();
let inp = vec![0_u8; 204800];
println!("Input size: {} Bytes", inp.len());
let mut fb = FB128::init(2, 2).unwrap();
println!("Encrypting...");
let now = Instant::now();
let _key = fb.add(&inp);
let elapsed = now.elapsed().as_secs_f32();
println!("Took {} secs", elapsed);
println!("Exporting...");
let encr = fb.to_bytes().0;
let rate = encr.len() as f32 / elapsed;
println!("Rate: {rate:.1} B/sec");
let extra = encr.len() - inp.len();
let percent = extra as f32/encr.len() as f32 * 100_f32;
println!("Extra Bytes: {extra} Bytes ({percent}%)");
}

BIN
input Normal file

Binary file not shown.

BIN
input1 Normal file

Binary file not shown.

View File

@ -2,11 +2,14 @@
use crate::{FBError, FBKey, FBObj, FBObjTrait, FieldOps, Packing};
use crypto_bigint::{NonZero, RandomMod};
use rand::{Rng, seq::IteratorRandom};
use rayon::iter::*;
use std::marker::Send;
use std::sync::RwLock;
pub trait FBAlgo<T>
where
Self: BlockOps<T>,
T: FieldOps + Packing + RandomMod,
Self: BlockOps<T> + Sync + Send,
T: FieldOps + Packing + RandomMod + Send,
{
const MODULUS: NonZero<T>;
@ -23,19 +26,20 @@ where
let r = (0..keybase_len)
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
let c = (0..cipher_len)
let c_vec = (0..cipher_len)
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
let c = RwLock::new(c_vec);
Ok(FBObj { c, r })
}
/// Adds the provided message to the ciphertext.
fn add(&mut self, msg: &[u8]) -> FBKey {
let indices = T::pack(msg)
.into_iter()
.map(|msg_uint| self.add_block(&msg_uint))
.collect();
.into_par_iter()
.map(|msg_uint| self.add_block(&msg_uint))
.collect();
FBKey { indices }
}
@ -45,7 +49,7 @@ where
/// [InvalidKey](FBError::InvalidKey)
fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> {
let decr = key.indices
.iter()
.par_iter()
.map(|index_row| self.decrypt_block(&index_row))
.collect::<Result<Vec<_>, _>>()?;
let mut msg = T::unpack(decr)?;
@ -61,25 +65,32 @@ where
Self: FBObjTrait<T>,
T: FieldOps + RandomMod,
{
fn add_block(&mut self, msg_uint: &T) -> Vec<(usize, usize)> {
let c = self.cipher();
fn add_block(&self, msg_uint: &T) -> Vec<(usize, usize)> {
let mut c_len = self.cipher().read().unwrap().len();
let r = self.keybase();
let mut rng = rand::thread_rng();
let n = rng.gen_range(2..=r.len());
let mut c_i = (0..c.len()).choose_multiple(&mut rng, n-1);
let mut c_i = (0..c_len).choose_multiple(&mut rng, n-1);
let r_i = (0..r.len()).choose_multiple(&mut rng, n);
let mut sum = T::ZERO;
for (&ci, &ri) in c_i.iter().zip( r_i.iter() ) {
sum = sum.field_add( &c[ci].field_mul(&r[ri]) );
}
let ri_last = *r_i.last()
.expect("r_i will contain at least 2 elements");
let mod_inv = r[ri_last].field_inv();
let ri_last_inv = r[ri_last].field_inv();
let mut sum = T::ZERO;
{
let c = self.cipher().read().unwrap();
for (&ci, &ri) in c_i.iter().zip( r_i.iter() ) {
sum = sum.field_add( &c[ci].field_mul(&r[ri]) );
}
}
let c_new_el = msg_uint.field_sub(&sum)
.field_mul(&mod_inv);
let c = self.cipher_mut();
c.push(c_new_el);
c_i.push(c.len() - 1);
.field_mul(&ri_last_inv);
{
let mut c = self.cipher().write().unwrap();
c.push(c_new_el);
c_len = c.len();
}
c_i.push(c_len - 1);
let indices = c_i.into_iter()
.zip(r_i.into_iter())
.collect();
@ -88,7 +99,7 @@ where
}
fn decrypt_block(&self, indices: &[(usize, usize)]) -> Result<T, FBError> {
let (c, r) = (self.cipher(), self.keybase());
let (c, r) = (self.cipher().read().unwrap(), self.keybase());
if indices.len() > r.len() {
return Err(FBError::InvalidKey);
}
@ -109,7 +120,8 @@ fn encrypt_u128() {
use crypto_bigint::U128;
let msg = U128::from_u32(100);
let mut fb = FBObj::<U128>::init(18, 12).unwrap();
let key = fb.add_block(&msg);
let lock = RwLock::new(&mut fb);
let key = FBObj::<U128>::add_block(&lock, &msg);
let decrypted = fb.decrypt_block(&key).unwrap();
assert_eq!(msg, decrypted);
}

View File

@ -2,6 +2,7 @@
use crate::{FBError, FBObj, FBObjTrait};
use crypto_bigint::{ArrayEncoding, Bounded, generic_array::GenericArray};
use base64::{prelude::BASE64_STANDARD, Engine};
use std::sync::RwLock;
pub trait Encode<T>
where
@ -10,7 +11,8 @@ where
{
/// Returns the byte representation of the ciphertext and keybase.
fn to_bytes(&self) -> (Vec<u8>, Vec<u8>) {
let c = self.cipher().iter()
let c = self.cipher().read().unwrap()
.iter()
.flat_map(|bigint| bigint.to_le_byte_array())
.collect();
let r = self.keybase().iter()
@ -36,15 +38,16 @@ where
T::from_le_byte_array(
GenericArray::clone_from_slice(chunk)
)};
let c: Vec<T> = cipher.chunks_exact(T::BYTES)
let c_vec: Vec<T> = cipher.chunks_exact(T::BYTES)
.map(chunk_to_uint)
.collect();
let r: Vec<T> = keybase.chunks_exact(T::BYTES)
.map(chunk_to_uint)
.collect();
if r.len() > c.len() || r.len() < 2 {
if r.len() > c_vec.len() || r.len() < 2 {
return Err(FBError::InvalidParams);
}
let c = RwLock::new(c_vec);
Ok(FBObj {c, r})
}

View File

@ -3,26 +3,23 @@ pub mod fb128;
use crate::{BlockOps, Encode, FieldOps};
use crypto_bigint::{ArrayEncoding, Bounded, RandomMod};
use std::sync::RwLock;
/// The False Bottom Object holds the ciphertext and the keybase. The provided type aliases can be used to pick a block size.
pub struct FBObj<T> {
pub(crate) c: Vec<T>,
pub(crate) c: RwLock<Vec<T>>,
pub(crate) r: Vec<T>,
}
pub trait FBObjTrait<T> {
fn cipher(&self) -> &Vec<T>;
fn cipher_mut(&mut self) -> &mut Vec<T>;
fn cipher(&self) -> &RwLock<Vec<T>>;
fn keybase(&self) -> &Vec<T>;
}
impl<T> FBObjTrait<T> for FBObj<T> {
fn cipher(&self) -> &Vec<T> {
fn cipher(&self) -> &RwLock<Vec<T>> {
&self.c
}
fn cipher_mut(&mut self) -> &mut Vec<T> {
&mut self.c
}
fn keybase(&self) -> &Vec<T> {
&self.r
}

View File

@ -19,12 +19,14 @@ where
const R_BOUND: Self;
fn pack(inp: &[u8]) -> Vec<Self> {
let mut cnt = 0;
let mut out: Vec<Self> = inp.chunks(Self::BYTES)
.flat_map(|inp_chunk| {
let mut out_chunk = GenericArray::<u8, Self::ByteSize>::default();
out_chunk[..inp_chunk.len()].copy_from_slice(inp_chunk);
let mut out_uint = Self::from_le_byte_array(out_chunk);
if out_uint >= Self::R_BOUND {
cnt += 1;
out_uint = out_uint.wrapping_sub(&Self::R_BOUND);
vec![Self::R_BOUND, out_uint]
} else {
@ -40,6 +42,8 @@ where
pad_chunk[Self::BYTES - 1] += (Self::BYTES - inp_chunk_last.len()) as u8;
}
out.push(Self::from_le_byte_array(pad_chunk));
eprintln!("Packing: Out of field: {cnt}");
out
}