190 lines
5.1 KiB
Rust
190 lines
5.1 KiB
Rust
|
|
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<u8, sizes::U16>) {
|
||
|
|
// 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<u8, sizes::U16>,
|
||
|
|
// sector_number: &Array<u8, sizes::U16>,
|
||
|
|
// block_number: u32,
|
||
|
|
// tweak_buff: &mut Array<u8, sizes::U16>,
|
||
|
|
// ) {
|
||
|
|
// 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<u8, sizes::U16>) -> Array<u8, sizes::U16> {
|
||
|
|
let cipher = Aes128::new(tweak_key);
|
||
|
|
let mut res: Array<u8, sizes::U16> = Array([0u8;16]);
|
||
|
|
cipher.encrypt_block(&mut res);
|
||
|
|
res
|
||
|
|
}
|
||
|
|
|
||
|
|
#[inline]
|
||
|
|
fn add_one_to_block_(block: &mut Array<u8, sizes::U16>) -> 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<u8, sizes::U16>,
|
||
|
|
b_arr: &Array<u8, sizes::U16>,
|
||
|
|
out_arr: &mut Array<u8, sizes::U16>,
|
||
|
|
) {
|
||
|
|
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<u8, sizes::U16>, b_arr: &Array<u8, sizes::U16>) {
|
||
|
|
a_arr
|
||
|
|
.iter_mut()
|
||
|
|
.zip(b_arr.iter())
|
||
|
|
.for_each(|(o, a)| *o ^= a);
|
||
|
|
}
|
||
|
|
|
||
|
|
// fn add_u64_to_arr_u8(arr: &Array<u8, sizes::U16>, b: u64) -> Array<u8, sizes::U16> {
|
||
|
|
// let mut res: Array<u8, sizes::U16> = 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<u8, sizes::U16>, 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<u8, sizes::U16>,
|
||
|
|
tweak: &Array<u8, sizes::U16>,
|
||
|
|
batch_size: u64,
|
||
|
|
in_block: &Array<u8, sizes::U16>,
|
||
|
|
search_block: &Array<u8, sizes::U16>,
|
||
|
|
) -> Option<Array<u8, sizes::U16>> {
|
||
|
|
let mut current_key = start_key.clone();
|
||
|
|
let mut out_block: Array<u8, sizes::U16> = 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<Array<u8, sizes::U16>> {
|
||
|
|
|
||
|
|
let (tx, rx) = mpsc::channel();
|
||
|
|
|
||
|
|
let th_num = pool.max_count();
|
||
|
|
|
||
|
|
let mut a_start_key: Array<u8, sizes::U16> = Array::from(start_key.clone());
|
||
|
|
let a_tweak_key: Array<u8, sizes::U16> = Array::from(tweak_key.clone());
|
||
|
|
let a_data_block: Array<u8, sizes::U16> = Array::from(data_block.clone());
|
||
|
|
let a_search_block: Array<u8, sizes::U16> = 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;
|
||
|
|
}
|