WIP: Threading done
This commit is contained in:
		
							parent
							
								
									1eca9a6aa0
								
							
						
					
					
						commit
						888c863628
					
				|  | @ -14,6 +14,7 @@ crypto-bigint = {version = "0.5.5", features = ["generic-array"]} | ||||||
| base64 = "0.21.7" | base64 = "0.21.7" | ||||||
| bincode = "1.3.3" | bincode = "1.3.3" | ||||||
| typenum = "1.17.0" | typenum = "1.17.0" | ||||||
|  | rayon = "1.10.0" | ||||||
| 
 | 
 | ||||||
| [lib] | [lib] | ||||||
| doctest = false | doctest = false | ||||||
|  | @ -2,13 +2,13 @@ use false_bottom::{FB128, FBKey, FBAlgo, Encode}; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
| 	// Cipher Initialization
 | 	// Cipher Initialization
 | ||||||
| 	let mut fb = FB128::init(18, 9).unwrap(); | 	let mut fb = FB128::init(2, 2).unwrap(); | ||||||
| 
 | 
 | ||||||
| 	// Encryption
 | 	// Encryption
 | ||||||
| 	let msg1 = "This is a message"; | 	let msg1 = "This is a message".as_bytes(); | ||||||
| 	let key1 = fb.add(msg1.as_bytes()); | 	let key1 = fb.add(msg1); | ||||||
| 	let msg2 = "This is another message"; | 	let msg2 = "This is another message".as_bytes(); | ||||||
| 	let key2 = fb.add(msg2.as_bytes()); | 	let key2 = fb.add(msg2); | ||||||
| 
 | 
 | ||||||
| 	// Export as base64
 | 	// Export as base64
 | ||||||
| 	let (cipher, keybase) = fb.export(); // Careful with the order
 | 	let (cipher, keybase) = fb.export(); // Careful with the order
 | ||||||
|  | @ -16,6 +16,14 @@ fn main() { | ||||||
| 	// Or as raw bytes
 | 	// Or as raw bytes
 | ||||||
| 	let key2_exp = key2.to_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
 | 	// Import from base64
 | ||||||
| 	let fb_new = FB128::import(&cipher, &keybase).unwrap(); | 	let fb_new = FB128::import(&cipher, &keybase).unwrap(); | ||||||
| 	let key1_imp = FBKey::import(&key1_exp).unwrap(); | 	let key1_imp = FBKey::import(&key1_exp).unwrap(); | ||||||
|  | @ -34,6 +42,6 @@ Key 1: {key1_exp} | ||||||
| Key 2: {key2_exp:?} | Key 2: {key2_exp:?} | ||||||
| ");
 | ");
 | ||||||
| 
 | 
 | ||||||
| 	assert_eq!(msg1.as_bytes(), decr1); | 	assert_eq!(msg1, decr1); | ||||||
| 	assert_eq!(msg2.as_bytes(), decr2); | 	assert_eq!(msg2, decr2); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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}%)"); | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								src/algo.rs
								
								
								
								
							
							
						
						
									
										44
									
								
								src/algo.rs
								
								
								
								
							|  | @ -2,11 +2,14 @@ | ||||||
| use crate::{FBError, FBKey, FBObj, FBObjTrait, FieldOps, Packing}; | use crate::{FBError, FBKey, FBObj, FBObjTrait, FieldOps, Packing}; | ||||||
| use crypto_bigint::{NonZero, RandomMod}; | use crypto_bigint::{NonZero, RandomMod}; | ||||||
| use rand::{Rng, seq::IteratorRandom}; | use rand::{Rng, seq::IteratorRandom}; | ||||||
|  | use rayon::iter::*; | ||||||
|  | use std::marker::Send; | ||||||
|  | use std::sync::RwLock; | ||||||
| 
 | 
 | ||||||
| pub trait FBAlgo<T> | pub trait FBAlgo<T> | ||||||
| where | where | ||||||
| 	Self: BlockOps<T>, | 	Self: BlockOps<T> + Sync + Send, | ||||||
| 	T: FieldOps + Packing + RandomMod, | 	T: FieldOps + Packing + RandomMod + Send, | ||||||
| { | { | ||||||
| 	const MODULUS: NonZero<T>; | 	const MODULUS: NonZero<T>; | ||||||
| 
 | 
 | ||||||
|  | @ -23,9 +26,10 @@ where | ||||||
| 		let r = (0..keybase_len) | 		let r = (0..keybase_len) | ||||||
| 			.map(|_| T::random_mod(&mut rng, &Self::MODULUS)) | 			.map(|_| T::random_mod(&mut rng, &Self::MODULUS)) | ||||||
| 			.collect(); | 			.collect(); | ||||||
| 		let c = (0..cipher_len) | 		let c_vec = (0..cipher_len) | ||||||
| 			.map(|_| T::random_mod(&mut rng, &Self::MODULUS)) | 			.map(|_| T::random_mod(&mut rng, &Self::MODULUS)) | ||||||
| 			.collect(); | 			.collect(); | ||||||
|  | 		let c = RwLock::new(c_vec); | ||||||
| 		
 | 		
 | ||||||
| 		Ok(FBObj { c, r }) | 		Ok(FBObj { c, r }) | ||||||
| 	} | 	} | ||||||
|  | @ -33,7 +37,7 @@ where | ||||||
| 	/// Adds the provided message to the ciphertext.
 | 	/// Adds the provided message to the ciphertext.
 | ||||||
| 	fn add(&mut self, msg: &[u8]) -> FBKey { | 	fn add(&mut self, msg: &[u8]) -> FBKey { | ||||||
| 		let indices = T::pack(msg) | 		let indices = T::pack(msg) | ||||||
| 			.into_iter() | 			.into_par_iter() | ||||||
| 			.map(|msg_uint|	self.add_block(&msg_uint)) | 			.map(|msg_uint|	self.add_block(&msg_uint)) | ||||||
| 			.collect(); 
 | 			.collect(); 
 | ||||||
| 
 | 
 | ||||||
|  | @ -45,7 +49,7 @@ where | ||||||
| 	/// [InvalidKey](FBError::InvalidKey)
 | 	/// [InvalidKey](FBError::InvalidKey)
 | ||||||
| 	fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> { | 	fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> { | ||||||
| 		let decr = key.indices | 		let decr = key.indices | ||||||
| 			.iter() | 			.par_iter() | ||||||
| 			.map(|index_row| self.decrypt_block(&index_row)) | 			.map(|index_row| self.decrypt_block(&index_row)) | ||||||
| 			.collect::<Result<Vec<_>, _>>()?; | 			.collect::<Result<Vec<_>, _>>()?; | ||||||
| 		let mut msg = T::unpack(decr)?; | 		let mut msg = T::unpack(decr)?; | ||||||
|  | @ -61,25 +65,32 @@ where | ||||||
| 	Self: FBObjTrait<T>, | 	Self: FBObjTrait<T>, | ||||||
| 	T: FieldOps + RandomMod, | 	T: FieldOps + RandomMod, | ||||||
| { | { | ||||||
| 	fn add_block(&mut self, msg_uint: &T) -> Vec<(usize, usize)> { | 	fn add_block(&self, msg_uint: &T) -> Vec<(usize, usize)> { | ||||||
| 		let c = self.cipher(); | 		let mut c_len = self.cipher().read().unwrap().len(); | ||||||
| 		let r = self.keybase(); | 		let r = self.keybase(); | ||||||
| 		let mut rng = rand::thread_rng(); | 		let mut rng = rand::thread_rng(); | ||||||
| 		let n = rng.gen_range(2..=r.len()); | 		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 r_i = (0..r.len()).choose_multiple(&mut rng, n); | ||||||
|  | 		let ri_last = *r_i.last() | ||||||
|  | 			.expect("r_i will contain at least 2 elements"); | ||||||
|  | 		let ri_last_inv = r[ri_last].field_inv(); | ||||||
| 		let mut sum = T::ZERO; | 		let mut sum = T::ZERO; | ||||||
|  | 		{ | ||||||
|  | 			let c = self.cipher().read().unwrap(); | ||||||
| 			for (&ci, &ri) in c_i.iter().zip( r_i.iter() ) { | 			for (&ci, &ri) in c_i.iter().zip( r_i.iter() ) { | ||||||
| 				sum = sum.field_add( &c[ci].field_mul(&r[ri]) ); | 				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 c_new_el = msg_uint.field_sub(&sum) | 		let c_new_el = msg_uint.field_sub(&sum) | ||||||
| 			.field_mul(&mod_inv); | 			.field_mul(&ri_last_inv); | ||||||
| 		let c = self.cipher_mut(); | 		{ | ||||||
|  | 			let mut c = self.cipher().write().unwrap(); | ||||||
| 			c.push(c_new_el); | 			c.push(c_new_el); | ||||||
| 		c_i.push(c.len() - 1); | 			c_len = c.len(); | ||||||
|  | 		} | ||||||
|  | 		c_i.push(c_len - 1); | ||||||
| 		let indices = c_i.into_iter() | 		let indices = c_i.into_iter() | ||||||
| 			.zip(r_i.into_iter()) | 			.zip(r_i.into_iter()) | ||||||
| 			.collect(); | 			.collect(); | ||||||
|  | @ -88,7 +99,7 @@ where | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn decrypt_block(&self, indices: &[(usize, usize)]) -> Result<T, FBError> { | 	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() { | 		if indices.len() > r.len() { | ||||||
| 			return Err(FBError::InvalidKey); | 			return Err(FBError::InvalidKey); | ||||||
| 		} | 		} | ||||||
|  | @ -109,7 +120,8 @@ fn encrypt_u128() { | ||||||
| 	use crypto_bigint::U128; | 	use crypto_bigint::U128; | ||||||
| 	let msg = U128::from_u32(100); | 	let msg = U128::from_u32(100); | ||||||
| 	let mut fb = FBObj::<U128>::init(18, 12).unwrap(); | 	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(); | 	let decrypted = fb.decrypt_block(&key).unwrap(); | ||||||
| 	assert_eq!(msg, decrypted); | 	assert_eq!(msg, decrypted); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| use crate::{FBError, FBObj, FBObjTrait}; | use crate::{FBError, FBObj, FBObjTrait}; | ||||||
| use crypto_bigint::{ArrayEncoding, Bounded, generic_array::GenericArray}; | use crypto_bigint::{ArrayEncoding, Bounded, generic_array::GenericArray}; | ||||||
| use base64::{prelude::BASE64_STANDARD, Engine}; | use base64::{prelude::BASE64_STANDARD, Engine}; | ||||||
|  | use std::sync::RwLock; | ||||||
| 
 | 
 | ||||||
| pub trait Encode<T> | pub trait Encode<T> | ||||||
| where | where | ||||||
|  | @ -10,7 +11,8 @@ where | ||||||
| { | { | ||||||
| 	/// Returns the byte representation of the ciphertext and keybase.
 | 	/// Returns the byte representation of the ciphertext and keybase.
 | ||||||
| 	fn to_bytes(&self) -> (Vec<u8>, Vec<u8>) { | 	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()) | 			.flat_map(|bigint| bigint.to_le_byte_array()) | ||||||
| 			.collect(); | 			.collect(); | ||||||
| 		let r = self.keybase().iter() | 		let r = self.keybase().iter() | ||||||
|  | @ -36,15 +38,16 @@ where | ||||||
| 			T::from_le_byte_array( | 			T::from_le_byte_array( | ||||||
| 				GenericArray::clone_from_slice(chunk) | 				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) | 			.map(chunk_to_uint) | ||||||
| 			.collect(); | 			.collect(); | ||||||
| 		let r: Vec<T> = keybase.chunks_exact(T::BYTES) | 		let r: Vec<T> = keybase.chunks_exact(T::BYTES) | ||||||
| 			.map(chunk_to_uint) | 			.map(chunk_to_uint) | ||||||
| 			.collect(); | 			.collect(); | ||||||
| 		if r.len() > c.len() || r.len() < 2 { | 		if r.len() > c_vec.len() || r.len() < 2 { | ||||||
| 			return Err(FBError::InvalidParams); | 			return Err(FBError::InvalidParams); | ||||||
| 		} | 		} | ||||||
|  | 		let c = RwLock::new(c_vec); | ||||||
| 
 | 
 | ||||||
| 		Ok(FBObj {c, r}) | 		Ok(FBObj {c, r}) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								src/fbobj.rs
								
								
								
								
							
							
						
						
									
										11
									
								
								src/fbobj.rs
								
								
								
								
							|  | @ -3,26 +3,23 @@ pub mod fb128; | ||||||
| 
 | 
 | ||||||
| use crate::{BlockOps, Encode, FieldOps}; | use crate::{BlockOps, Encode, FieldOps}; | ||||||
| use crypto_bigint::{ArrayEncoding, Bounded, RandomMod}; | 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.
 | /// 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 struct FBObj<T> { | ||||||
| 	pub(crate) c: Vec<T>, | 	pub(crate) c: RwLock<Vec<T>>, | ||||||
| 	pub(crate) r: Vec<T>, | 	pub(crate) r: Vec<T>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait FBObjTrait<T> { | pub trait FBObjTrait<T> { | ||||||
| 	fn cipher(&self) -> &Vec<T>; | 	fn cipher(&self) -> &RwLock<Vec<T>>; | ||||||
| 	fn cipher_mut(&mut self) -> &mut Vec<T>; |  | ||||||
| 	fn keybase(&self) -> &Vec<T>; | 	fn keybase(&self) -> &Vec<T>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<T> FBObjTrait<T> for FBObj<T> { | impl<T> FBObjTrait<T> for FBObj<T> { | ||||||
| 	fn cipher(&self) -> &Vec<T> { | 	fn cipher(&self) -> &RwLock<Vec<T>> { | ||||||
| 		&self.c | 		&self.c | ||||||
| 	} | 	} | ||||||
| 	fn cipher_mut(&mut self) -> &mut Vec<T> { |  | ||||||
| 		&mut self.c |  | ||||||
| 	} |  | ||||||
| 	fn keybase(&self) -> &Vec<T> { | 	fn keybase(&self) -> &Vec<T> { | ||||||
| 		&self.r | 		&self.r | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -19,12 +19,14 @@ where | ||||||
| 	const R_BOUND: Self; | 	const R_BOUND: Self; | ||||||
| 
 | 
 | ||||||
| 	fn pack(inp: &[u8]) -> Vec<Self> { | 	fn pack(inp: &[u8]) -> Vec<Self> { | ||||||
|  | 		let mut cnt = 0; | ||||||
| 		let mut out: Vec<Self> = inp.chunks(Self::BYTES) | 		let mut out: Vec<Self> = inp.chunks(Self::BYTES) | ||||||
| 			.flat_map(|inp_chunk| { | 			.flat_map(|inp_chunk| { | ||||||
| 				let mut out_chunk = GenericArray::<u8, Self::ByteSize>::default(); | 				let mut out_chunk = GenericArray::<u8, Self::ByteSize>::default(); | ||||||
| 				out_chunk[..inp_chunk.len()].copy_from_slice(inp_chunk); | 				out_chunk[..inp_chunk.len()].copy_from_slice(inp_chunk); | ||||||
| 				let mut out_uint = Self::from_le_byte_array(out_chunk); | 				let mut out_uint = Self::from_le_byte_array(out_chunk); | ||||||
| 				if out_uint >= Self::R_BOUND { | 				if out_uint >= Self::R_BOUND { | ||||||
|  | 					cnt += 1; | ||||||
| 					out_uint = out_uint.wrapping_sub(&Self::R_BOUND); | 					out_uint = out_uint.wrapping_sub(&Self::R_BOUND); | ||||||
| 					vec![Self::R_BOUND, out_uint] | 					vec![Self::R_BOUND, out_uint] | ||||||
| 				} else { | 				} else { | ||||||
|  | @ -40,6 +42,8 @@ where | ||||||
| 			pad_chunk[Self::BYTES - 1] += (Self::BYTES - inp_chunk_last.len()) as u8; | 			pad_chunk[Self::BYTES - 1] += (Self::BYTES - inp_chunk_last.len()) as u8; | ||||||
| 		} | 		} | ||||||
| 		out.push(Self::from_le_byte_array(pad_chunk)); | 		out.push(Self::from_le_byte_array(pad_chunk)); | ||||||
|  | 		eprintln!("Packing: Out of field: {cnt}"); | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 		out | 		out | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue