use aes; use aes::Aes128; use aes::cipher::array::sizes; use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; use std::sync::mpsc; use threadpool::ThreadPool; /// Galois field multiplication /// Multiplies a 128-bit block by x in GF(2^128) for AES-XTS. /// The irreducible polynomial used is x^128 + x^7 + x^2 + x + 1 (0x87). // #[inline] // fn gf128_mul_by_x(block: &mut Array) { // let mut carry = 0u8; // // Process bytes from most significant (15) to least significant (0) // for byte in block.iter_mut().rev() { // let temp = *byte; // *byte = (*byte << 1) | carry; // carry = temp >> 7; // The bit that was shifted out // } // // If the most significant bit of the original block was 1, apply reduction // if carry != 0 { // block[15] ^= 0x87; // XOR with the reduction polynomial // } // } // #[inline] // fn aes_xts256_gen_tweak( // tweak_key: &Array, // sector_number: &Array, // block_number: u32, // tweak_buff: &mut Array, // ) { // let cipher = Aes128::new(tweak_key); // cipher.encrypt_block_b2b(sector_number, tweak_buff); // //Double the tweak value block_n-1 times (since first block is 0) // for _ in 0..block_number { // gf128_mul_by_x(tweak_buff); // } // } #[inline] fn gen_tweak_zero_block(tweak_key: &Array) -> Array { let cipher = Aes128::new(tweak_key); let mut res: Array = Array([0u8;16]); cipher.encrypt_block(&mut res); res } #[inline] fn add_one_to_block_(block: &mut Array) -> bool { let mut carry = false; (block[0], carry) = block[0].carrying_add(1u8, carry); for i in 1..16 { if carry == false { break; } (block[i], carry) = block[i].carrying_add(0u8, carry); } carry } #[inline] fn xor_arrays( a_arr: &Array, b_arr: &Array, out_arr: &mut Array, ) { out_arr .iter_mut() .zip(a_arr.iter().zip(b_arr.iter())) .for_each(|(o, (a, b))| *o = a ^ b); } #[inline] fn xor_array_(a_arr: &mut Array, b_arr: &Array) { a_arr .iter_mut() .zip(b_arr.iter()) .for_each(|(o, a)| *o ^= a); } // fn add_u64_to_arr_u8(arr: &Array, b: u64) -> Array { // let mut res: Array = Array([0u8; 16]); // let b_bytes = b.to_le_bytes(); // let mut carry: bool = false; // for i in 0..8 { // (res[i], carry) = arr[i].carrying_add(b_bytes[i], carry); // } // for i in 8..16 { // (res[i], carry) = arr[i].carrying_add(0u8, carry); // } // res // } fn add_u64_to_arr_u8_(arr: &mut Array, b: u64) -> bool { let b_bytes = b.to_le_bytes(); let mut carry: bool = false; for i in 0..8 { (arr[i], carry) = arr[i].carrying_add(b_bytes[i], carry); } for i in 8..16 { (arr[i], carry) = arr[i].carrying_add(0u8, carry); } carry } pub fn encrypt_and_check( start_key: &Array, tweak: &Array, batch_size: u64, in_block: &Array, search_block: &Array, ) -> Option> { let mut current_key = start_key.clone(); let mut out_block: Array = Array::from([0u8; 16]); for _b_num in 0..batch_size { // Initialize cipher let cipher = Aes128::new(¤t_key); xor_arrays(in_block, tweak, &mut out_block); // Encrypt block in-place cipher.encrypt_block(&mut out_block); xor_array_(&mut out_block, tweak); if out_block.eq(search_block) { return Some(current_key); } let _ = add_one_to_block_(&mut current_key); } return None; } pub fn do_work( pool: &ThreadPool, batch_size: u64, start_key: &[u8; 16], tweak_key: &[u8; 16], data_block: &[u8; 16], search_block: &[u8; 16], ) -> Option> { let (tx, rx) = mpsc::channel(); let th_num = pool.max_count(); let mut a_start_key: Array = Array::from(start_key.clone()); let a_tweak_key: Array = Array::from(tweak_key.clone()); let a_data_block: Array = Array::from(data_block.clone()); let a_search_block: Array = Array::from(search_block.clone()); let tweak = gen_tweak_zero_block(&a_tweak_key); for _ in 0..th_num { let th_start_key = a_start_key.clone(); let tx = tx.clone(); pool.execute(move || { let result = encrypt_and_check( &th_start_key, &tweak, batch_size, &a_data_block, &a_search_block, ); tx.send(result).unwrap(); }); add_u64_to_arr_u8_(&mut a_start_key, batch_size); } drop(tx); // Close the sending end // Collect all results let results = rx.iter() .find(|x| x.is_some()) .unwrap_or(None); return results; }