From 888c8636283af25f327dbb1f4cf4bba2e9ed84f2 Mon Sep 17 00:00:00 2001 From: K Shiva Kiran Date: Thu, 11 Apr 2024 20:23:26 +0530 Subject: [PATCH] WIP: Threading done --- Cargo.toml | 1 + examples/export.rs | 22 ++++++++++++------ examples/file.rs | 23 +++++++++++++++++++ input | Bin 0 -> 102400 bytes input1 | Bin 0 -> 204800 bytes src/algo.rs | 56 +++++++++++++++++++++++++++------------------ src/encoding.rs | 9 +++++--- src/fbobj.rs | 11 ++++----- src/packing.rs | 4 ++++ 9 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 examples/file.rs create mode 100644 input create mode 100644 input1 diff --git a/Cargo.toml b/Cargo.toml index 9d0c0fc..981b941 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 \ No newline at end of file diff --git a/examples/export.rs b/examples/export.rs index 6bb3d46..4c0df7f 100644 --- a/examples/export.rs +++ b/examples/export.rs @@ -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); } diff --git a/examples/file.rs b/examples/file.rs new file mode 100644 index 0000000..22ede5f --- /dev/null +++ b/examples/file.rs @@ -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}%)"); +} diff --git a/input b/input new file mode 100644 index 0000000000000000000000000000000000000000..da1dfb90e7c41de55aeb63d311937cdac9edd929 GIT binary patch literal 102400 zcmeIufdBvi0K=g9Qy=7oP+`D;0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfPs&J0gw*> A0RR91 literal 0 HcmV?d00001 diff --git a/input1 b/input1 new file mode 100644 index 0000000000000000000000000000000000000000..52972ec9e05fbb995e2efd1ed651077d4cd226a8 GIT binary patch literal 204800 zcmeIu0Sy2E0K%a6Pi+qe5hx58Fkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj fFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*2A&26AT0m^ literal 0 HcmV?d00001 diff --git a/src/algo.rs b/src/algo.rs index 98c337b..9f59fb5 100644 --- a/src/algo.rs +++ b/src/algo.rs @@ -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 where - Self: BlockOps, - T: FieldOps + Packing + RandomMod, + Self: BlockOps + Sync + Send, + T: FieldOps + Packing + RandomMod + Send, { const MODULUS: NonZero; @@ -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, FBError> { let decr = key.indices - .iter() + .par_iter() .map(|index_row| self.decrypt_block(&index_row)) .collect::, _>>()?; let mut msg = T::unpack(decr)?; @@ -61,25 +65,32 @@ where Self: FBObjTrait, 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 { - 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::::init(18, 12).unwrap(); - let key = fb.add_block(&msg); + let lock = RwLock::new(&mut fb); + let key = FBObj::::add_block(&lock, &msg); let decrypted = fb.decrypt_block(&key).unwrap(); assert_eq!(msg, decrypted); } diff --git a/src/encoding.rs b/src/encoding.rs index 1dfef77..b034353 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -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 where @@ -10,7 +11,8 @@ where { /// Returns the byte representation of the ciphertext and keybase. fn to_bytes(&self) -> (Vec, Vec) { - 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 = cipher.chunks_exact(T::BYTES) + let c_vec: Vec = cipher.chunks_exact(T::BYTES) .map(chunk_to_uint) .collect(); let r: Vec = 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}) } diff --git a/src/fbobj.rs b/src/fbobj.rs index 4d929d5..0436afc 100644 --- a/src/fbobj.rs +++ b/src/fbobj.rs @@ -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 { - pub(crate) c: Vec, + pub(crate) c: RwLock>, pub(crate) r: Vec, } pub trait FBObjTrait { - fn cipher(&self) -> &Vec; - fn cipher_mut(&mut self) -> &mut Vec; + fn cipher(&self) -> &RwLock>; fn keybase(&self) -> &Vec; } impl FBObjTrait for FBObj { - fn cipher(&self) -> &Vec { + fn cipher(&self) -> &RwLock> { &self.c } - fn cipher_mut(&mut self) -> &mut Vec { - &mut self.c - } fn keybase(&self) -> &Vec { &self.r } diff --git a/src/packing.rs b/src/packing.rs index acb06a5..d706018 100644 --- a/src/packing.rs +++ b/src/packing.rs @@ -19,12 +19,14 @@ where const R_BOUND: Self; fn pack(inp: &[u8]) -> Vec { + let mut cnt = 0; let mut out: Vec = inp.chunks(Self::BYTES) .flat_map(|inp_chunk| { let mut out_chunk = GenericArray::::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 }