diff options
Diffstat (limited to 'src/crack.rs')
-rw-r--r-- | src/crack.rs | 402 |
1 files changed, 234 insertions, 168 deletions
diff --git a/src/crack.rs b/src/crack.rs index acc059b..9d56980 100644 --- a/src/crack.rs +++ b/src/crack.rs @@ -1,20 +1,19 @@ -use std::ascii::AsciiExt; +use rand::Rng; use std::borrow::ToOwned; use std::collections::{HashMap, HashSet}; -use rand::{Rng, SeedableRng}; -use aes::encrypt_aes_128_cbc; -use data::ENGLISH_FREQUENCIES; -use primitives::{fixed_xor, unpad_pkcs7, hamming, repeating_key_xor}; -use random::MersenneTwister; +use crate::aes::encrypt_aes_128_cbc; +use crate::data::ENGLISH_FREQUENCIES; +use crate::primitives::{fixed_xor, hamming, repeating_key_xor, unpad_pkcs7}; +use crate::random::MersenneTwister; -#[derive(PartialEq,Eq,Debug)] +#[derive(PartialEq, Eq, Debug)] pub enum BlockCipherMode { ECB, CBC, } -pub fn find_single_byte_xor_encrypted_string (inputs: &[Vec<u8>]) -> Vec<u8> { +pub fn find_single_byte_xor_encrypted_string(inputs: &[Vec<u8>]) -> Vec<u8> { let mut min_diff = 100.0; let mut best_decrypted = vec![]; for input in inputs { @@ -27,44 +26,40 @@ pub fn find_single_byte_xor_encrypted_string (inputs: &[Vec<u8>]) -> Vec<u8> { return best_decrypted; } -pub fn crack_single_byte_xor (input: &[u8]) -> Vec<u8> { +pub fn crack_single_byte_xor(input: &[u8]) -> Vec<u8> { let (key, _) = crack_single_byte_xor_with_confidence(input); return repeating_key_xor(input, &[key]); } -pub fn crack_repeating_key_xor (input: &[u8]) -> Vec<u8> { +pub fn crack_repeating_key_xor(input: &[u8]) -> Vec<u8> { let mut keysizes = vec![]; for keysize in 2..40 { let distance1 = hamming( &input[(keysize * 0)..(keysize * 1)], - &input[(keysize * 1)..(keysize * 2)] + &input[(keysize * 1)..(keysize * 2)], ) as f64; let distance2 = hamming( &input[(keysize * 1)..(keysize * 2)], - &input[(keysize * 2)..(keysize * 3)] + &input[(keysize * 2)..(keysize * 3)], ) as f64; let distance3 = hamming( &input[(keysize * 2)..(keysize * 3)], - &input[(keysize * 3)..(keysize * 4)] + &input[(keysize * 3)..(keysize * 4)], ) as f64; let distance = distance1 + distance2 + distance3 / 3.0; let normal_distance = distance / (keysize as f64); keysizes.push((keysize, normal_distance)); if keysizes.len() > 5 { - let (idx, _) = keysizes - .iter() - .enumerate() - .fold( - (0, (0, 0.0)), - |(accidx, (accsize, accdist)), (idx, &(size, dist))| { - if dist > accdist { - (idx, (size, dist)) - } - else { - (accidx, (accsize, accdist)) - } + let (idx, _) = keysizes.iter().enumerate().fold( + (0, (0, 0.0)), + |(accidx, (accsize, accdist)), (idx, &(size, dist))| { + if dist > accdist { + (idx, (size, dist)) + } else { + (accidx, (accsize, accdist)) } - ); + }, + ); keysizes.swap_remove(idx); } } @@ -72,7 +67,8 @@ pub fn crack_repeating_key_xor (input: &[u8]) -> Vec<u8> { let mut min_diff = 100.0; let mut best_key = vec![]; for (keysize, _) in keysizes { - let (key, diff) = crack_repeating_key_xor_with_keysize(input, keysize); + let (key, diff) = + crack_repeating_key_xor_with_keysize(input, keysize); if diff < min_diff { min_diff = diff; best_key = key; @@ -82,7 +78,7 @@ pub fn crack_repeating_key_xor (input: &[u8]) -> Vec<u8> { return best_key; } -pub fn find_aes_128_ecb_encrypted_string (inputs: &[Vec<u8>]) -> Vec<u8> { +pub fn find_aes_128_ecb_encrypted_string(inputs: &[Vec<u8>]) -> Vec<u8> { let mut max_dups = 0; let mut found = vec![]; for input in inputs { @@ -95,27 +91,32 @@ pub fn find_aes_128_ecb_encrypted_string (inputs: &[Vec<u8>]) -> Vec<u8> { return found; } -pub fn detect_ecb_cbc<F> (f: &F, block_size: usize) -> BlockCipherMode where F: Fn(&[u8]) -> Vec<u8> { - if block_size >= ::std::u8::MAX as usize { +pub fn detect_ecb_cbc<F>(f: &F, block_size: usize) -> BlockCipherMode +where + F: Fn(&[u8]) -> Vec<u8>, +{ + if block_size >= std::u8::MAX as usize { panic!("invalid block size: {}", block_size); } let block_size_byte = block_size as u8; let plaintext: Vec<u8> = (0..block_size_byte) .cycle() .take(block_size * 2) - .flat_map(|n| ::std::iter::repeat(n).take(block_size + 1)) + .flat_map(|n| std::iter::repeat(n).take(block_size + 1)) .collect(); let ciphertext = f(&plaintext[..]); if count_duplicate_blocks(&ciphertext[..], block_size) >= block_size { return BlockCipherMode::ECB; - } - else { + } else { return BlockCipherMode::CBC; } } -pub fn crack_padded_aes_128_ecb<F> (f: &F) -> Vec<u8> where F: Fn(&[u8]) -> Vec<u8> { +pub fn crack_padded_aes_128_ecb<F>(f: &F) -> Vec<u8> +where + F: Fn(&[u8]) -> Vec<u8>, +{ let block_size = find_block_size(f); if detect_ecb_cbc(f, block_size) != BlockCipherMode::ECB { panic!("Can only crack ECB-encrypted data"); @@ -135,7 +136,7 @@ pub fn crack_padded_aes_128_ecb<F> (f: &F) -> Vec<u8> where F: Fn(&[u8]) -> Vec< loop { let mut map = HashMap::new(); - let prefix: Vec<u8> = ::std::iter::repeat(b'A') + let prefix: Vec<u8> = std::iter::repeat(b'A') .take(block_size - ((i % block_size) + 1)) .collect(); for c in 0..256 { @@ -150,22 +151,26 @@ pub fn crack_padded_aes_128_ecb<F> (f: &F) -> Vec<u8> where F: Fn(&[u8]) -> Vec< let next_char = map.get(&get_block(&prefix[..], i)); if next_char.is_some() { plaintext.push(*next_char.unwrap()); - } - else { + } else { break; } i += 1; } - return unpad_pkcs7(&plaintext[..]).expect("invalid padding").to_vec(); + return unpad_pkcs7(&plaintext[..]) + .expect("invalid padding") + .to_vec(); } -pub fn crack_padded_aes_128_ecb_with_prefix<F> (f: &F) -> Vec<u8> where F: Fn(&[u8]) -> Vec<u8> { +pub fn crack_padded_aes_128_ecb_with_prefix<F>(f: &F) -> Vec<u8> +where + F: Fn(&[u8]) -> Vec<u8>, +{ let (block_size, prefix_len) = find_block_size_and_fixed_prefix_len(f); let wrapped_f = |input: &[u8]| { let alignment_padding = block_size - (prefix_len % block_size); - let padded_input: Vec<u8> = ::std::iter::repeat(b'A') + let padded_input: Vec<u8> = std::iter::repeat(b'A') .take(alignment_padding) .chain(input.iter().map(|x| *x)) .collect(); @@ -178,8 +183,13 @@ pub fn crack_padded_aes_128_ecb_with_prefix<F> (f: &F) -> Vec<u8> where F: Fn(&[ return crack_padded_aes_128_ecb(&wrapped_f); } -pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>>) where F: Fn(&str) -> Vec<u8> { - fn incr_map_element (map: &mut HashMap<Vec<u8>, usize>, key: Vec<u8>) { +pub fn crack_querystring_aes_128_ecb<F>( + encrypter: &F, +) -> (String, Vec<Vec<u8>>) +where + F: Fn(&str) -> Vec<u8>, +{ + fn incr_map_element(map: &mut HashMap<Vec<u8>, usize>, key: Vec<u8>) { if let Some(val) = map.get_mut(&key) { *val += 1; return; @@ -191,8 +201,8 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> let find_uid_role_blocks = || { let mut map = HashMap::new(); for c in 32..127 { - let email_bytes: Vec<u8> = ::std::iter::repeat(c).take(9).collect(); - let email = ::std::str::from_utf8(&email_bytes[..]).unwrap(); + let email_bytes: Vec<u8> = std::iter::repeat(c).take(9).collect(); + let email = std::str::from_utf8(&email_bytes[..]).unwrap(); let ciphertext = encrypter(email); incr_map_element(&mut map, ciphertext[..16].to_vec()); incr_map_element(&mut map, ciphertext[16..32].to_vec()); @@ -202,20 +212,16 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> for (k, v) in map { most_common_blocks.push((k, v)); if most_common_blocks.len() > 2 { - let (idx, _) = most_common_blocks - .iter() - .enumerate() - .fold( - (0, (vec![], 10000)), - |(aidx, (ablock, acount)), (idx, &(ref block, count))| { - if count < acount { - (idx, (block.clone(), count)) - } - else { - (aidx, (ablock.clone(), acount)) - } + let (idx, _) = most_common_blocks.iter().enumerate().fold( + (0, (vec![], 10000)), + |(aidx, (ablock, acount)), (idx, &(ref block, count))| { + if count < acount { + (idx, (block.clone(), count)) + } else { + (aidx, (ablock.clone(), acount)) } - ); + }, + ); most_common_blocks.swap_remove(idx); } } @@ -224,8 +230,7 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> let (ref block1, _) = most_common_blocks[0]; let (ref block2, _) = most_common_blocks[1]; return (block1.clone(), block2.clone()); - } - else { + } else { panic!("couldn't find most common blocks"); } }; @@ -234,9 +239,12 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> // email=..........admin<pcks7 padding>...............&uid=10&role=user let calculate_admin_block = |block1: Vec<u8>, block2: Vec<u8>| { for _ in 0..1000 { - let email = "blorg@bar.admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b..............."; + let email = + "blorg@bar.admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b..............."; let ciphertext = encrypter(email); - if &ciphertext[48..64] == &block1[..] || &ciphertext[48..64] == &block2[..] { + if &ciphertext[48..64] == &block1[..] + || &ciphertext[48..64] == &block2[..] + { return ciphertext[16..32].to_vec(); } } @@ -256,7 +264,10 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> .chain(admin_block.iter()) .map(|x| *x) .collect(); - if !possibles.iter().any(|possible| possible == &modified_ciphertext) { + if !possibles + .iter() + .any(|possible| possible == &modified_ciphertext) + { possibles.push(modified_ciphertext); } } @@ -268,7 +279,10 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> return calculate_possible_admin_ciphertexts(admin_block); } -pub fn crack_cbc_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> { +pub fn crack_cbc_bitflipping<F>(f: &F) -> Vec<u8> +where + F: Fn(&str) -> Vec<u8>, +{ let mut ciphertext = f("AAAAAAAAAAAAAAAA:admin<true:AAAA"); ciphertext[32] = ciphertext[32] ^ 0x01; ciphertext[38] = ciphertext[38] ^ 0x01; @@ -276,7 +290,14 @@ pub fn crack_cbc_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> return ciphertext; } -pub fn crack_cbc_padding_oracle<F> (iv: &[u8], ciphertext: &[u8], f: &F) -> Vec<u8> where F: Fn(&[u8], &[u8]) -> bool { +pub fn crack_cbc_padding_oracle<F>( + iv: &[u8], + ciphertext: &[u8], + f: &F, +) -> Vec<u8> +where + F: Fn(&[u8], &[u8]) -> bool, +{ let mut prev = iv; let mut plaintext = vec![]; for block in ciphertext.chunks(16) { @@ -285,14 +306,15 @@ pub fn crack_cbc_padding_oracle<F> (iv: &[u8], ciphertext: &[u8], f: &F) -> Vec< for c_int in 0..256 { let c = (255 - c_int) as u8; let offset = (16 - byte - 1) as usize; - let mut iv: Vec<u8> = prev - .iter() - .take(offset) - .map(|x| *x) - .collect(); + let mut iv: Vec<u8> = + prev.iter().take(offset).map(|x| *x).collect(); iv.push(prev[offset] ^ c ^ (byte + 1)); for i in 0..(byte as usize) { - iv.push(prev[offset + i + 1] ^ plaintext_block[i] ^ (byte + 1)); + iv.push( + prev[offset + i + 1] + ^ plaintext_block[i] + ^ (byte + 1), + ); } if f(&iv[..], block) { plaintext_block.insert(0, c); @@ -309,7 +331,9 @@ pub fn crack_cbc_padding_oracle<F> (iv: &[u8], ciphertext: &[u8], f: &F) -> Vec< return unpad_pkcs7(&plaintext[..]).unwrap().to_vec(); } -pub fn crack_fixed_nonce_ctr_statistically (input: Vec<Vec<u8>>) -> Vec<Vec<u8>> { +pub fn crack_fixed_nonce_ctr_statistically( + input: Vec<Vec<u8>>, +) -> Vec<Vec<u8>> { let min_len = input.iter().map(|line| line.len()).min().unwrap(); let max_len = input.iter().map(|line| line.len()).max().unwrap(); @@ -328,8 +352,7 @@ pub fn crack_fixed_nonce_ctr_statistically (input: Vec<Vec<u8>>) -> Vec<Vec<u8>> if line.len() >= len { idxs.push(idx); true - } - else { + } else { false } }) @@ -337,10 +360,8 @@ pub fn crack_fixed_nonce_ctr_statistically (input: Vec<Vec<u8>>) -> Vec<Vec<u8>> .map(|x| *x) .collect(); - let (key, _) = crack_repeating_key_xor_with_keysize( - &ciphertext[..], - len - ); + let (key, _) = + crack_repeating_key_xor_with_keysize(&ciphertext[..], len); for i in full_key.len()..key.len() { full_key.push(key[i]) } @@ -358,11 +379,11 @@ pub fn crack_fixed_nonce_ctr_statistically (input: Vec<Vec<u8>>) -> Vec<Vec<u8>> return plaintext_lines; } -pub fn recover_mersenne_twister_seed_from_time (output: u32) -> Option<u32> { - let now = ::time::now().to_timespec().sec as u32; +pub fn recover_mersenne_twister_seed_from_time(output: u32) -> Option<u32> { + let now = time::now().to_timespec().sec as u32; for i in -10000..10000i32 { let seed = (now as i32).wrapping_add(i) as u32; - let mut mt = MersenneTwister::from_seed(seed); + let mut mt = MersenneTwister::from_u32(seed); let test_output: u32 = mt.gen(); if test_output == output { return Some(seed); @@ -371,9 +392,14 @@ pub fn recover_mersenne_twister_seed_from_time (output: u32) -> Option<u32> { return None; } -pub fn clone_mersenne_twister_from_output (outputs: &[u32]) -> MersenneTwister { - fn untemper (val: u32) -> u32 { - fn unxorshift<F> (f: F, mut y: u32, n: usize, mask: u32) -> u32 where F: Fn(u32, usize) -> u32 { +pub fn clone_mersenne_twister_from_output( + outputs: &[u32], +) -> MersenneTwister { + fn untemper(val: u32) -> u32 { + fn unxorshift<F>(f: F, mut y: u32, n: usize, mask: u32) -> u32 + where + F: Fn(u32, usize) -> u32, + { let mut a = y; for _ in 0..(32 / n) { y = f(y, n) & mask; @@ -384,10 +410,10 @@ pub fn clone_mersenne_twister_from_output (outputs: &[u32]) -> MersenneTwister { let mut y = val; - y = unxorshift(|a, n| {a >> n}, y, 18, 0xffffffff); - y = unxorshift(|a, n| {a << n}, y, 15, 0xefc60000); - y = unxorshift(|a, n| {a << n}, y, 7, 0x9d2c5680); - y = unxorshift(|a, n| {a >> n}, y, 11, 0xffffffff); + y = unxorshift(|a, n| a >> n, y, 18, 0xffffffff); + y = unxorshift(|a, n| a << n, y, 15, 0xefc60000); + y = unxorshift(|a, n| a << n, y, 7, 0x9d2c5680); + y = unxorshift(|a, n| a >> n, y, 11, 0xffffffff); y } @@ -397,16 +423,17 @@ pub fn clone_mersenne_twister_from_output (outputs: &[u32]) -> MersenneTwister { state[i] = untemper(output); } - return MersenneTwister::from_seed((state, 0)); + return MersenneTwister::from_state(state, 0); } -pub fn recover_16_bit_mt19937_key (ciphertext: &[u8], suffix: &[u8]) -> Option<u16> { +pub fn recover_16_bit_mt19937_key( + ciphertext: &[u8], + suffix: &[u8], +) -> Option<u16> { for _key in 0..65536u32 { let key = _key as u16; - let plaintext = ::random::mt19937_stream_cipher( - ciphertext, - key as u32 - ); + let plaintext = + crate::random::mt19937_stream_cipher(ciphertext, key as u32); if &plaintext[(ciphertext.len() - suffix.len())..] == suffix { return Some(key); } @@ -415,12 +442,15 @@ pub fn recover_16_bit_mt19937_key (ciphertext: &[u8], suffix: &[u8]) -> Option<u return None; } -pub fn recover_mt19937_key_from_time (token: &[u8]) -> Option<u32> { - let now = ::time::now().to_timespec().sec as u32; +pub fn recover_mt19937_key_from_time(token: &[u8]) -> Option<u32> { + let now = time::now().to_timespec().sec as u32; for i in -500..500i32 { let seed = (now as i32).wrapping_add(i) as u32; - let mut mt = MersenneTwister::from_seed(seed); - let test_token: Vec<u8> = mt.gen_iter().take(16).collect(); + let mut mt = MersenneTwister::from_u32(seed); + let test_token: Vec<u8> = mt + .sample_iter(&rand::distributions::Standard) + .take(16) + .collect(); if &test_token[..] == token { return Some(seed); } @@ -428,15 +458,23 @@ pub fn recover_mt19937_key_from_time (token: &[u8]) -> Option<u32> { return None; } -pub fn crack_aes_128_ctr_random_access<F> (ciphertext: &[u8], edit: F) -> Vec<u8> where F: Fn(&[u8], usize, &[u8]) -> Vec<u8> { - let empty_plaintext: Vec<u8> = ::std::iter::repeat(b'\x00') - .take(ciphertext.len()) - .collect(); +pub fn crack_aes_128_ctr_random_access<F>( + ciphertext: &[u8], + edit: F, +) -> Vec<u8> +where + F: Fn(&[u8], usize, &[u8]) -> Vec<u8>, +{ + let empty_plaintext: Vec<u8> = + std::iter::repeat(b'\x00').take(ciphertext.len()).collect(); let keystream = edit(ciphertext, 0, &empty_plaintext[..]); return fixed_xor(&keystream[..], ciphertext); } -pub fn crack_ctr_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> { +pub fn crack_ctr_bitflipping<F>(f: &F) -> Vec<u8> +where + F: Fn(&str) -> Vec<u8>, +{ let ciphertext = f("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); let replacement = fixed_xor(&ciphertext[32..44], b";admin=true;"); return ciphertext[..32] @@ -447,14 +485,18 @@ pub fn crack_ctr_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> .collect(); } -pub fn crack_cbc_iv_key<F1, F2> (encrypt: &F1, verify: &F2) -> Vec<u8> where F1: Fn(&str) -> Vec<u8>, F2: Fn(&[u8]) -> Result<bool, Vec<u8>> { +pub fn crack_cbc_iv_key<F1, F2>(encrypt: &F1, verify: &F2) -> Vec<u8> +where + F1: Fn(&str) -> Vec<u8>, + F2: Fn(&[u8]) -> Result<bool, Vec<u8>>, +{ loop { - let plaintext_bytes: Vec<u8> = ::rand::thread_rng() - .gen_iter() + let plaintext_bytes: Vec<u8> = rand::thread_rng() + .sample_iter(&rand::distributions::Standard) .filter(|&c| c >= 32 && c < 127) - .take(16*5) + .take(16 * 5) .collect(); - let plaintext = ::std::str::from_utf8(&plaintext_bytes).unwrap(); + let plaintext = std::str::from_utf8(&plaintext_bytes).unwrap(); let ciphertext = encrypt(plaintext); let modified_ciphertext: Vec<u8> = ciphertext[..16] .iter() @@ -466,7 +508,7 @@ pub fn crack_cbc_iv_key<F1, F2> (encrypt: &F1, verify: &F2) -> Vec<u8> where F1: if let Err(modified_plaintext) = verify(&modified_ciphertext[..]) { let key = fixed_xor( &modified_plaintext[..16], - &modified_plaintext[32..48] + &modified_plaintext[32..48], ); let desired_plaintext = b"comment1=cooking%20MCs;userdata=;admin=true;comment2=%20like%20a%20pound%20of%20bacon"; return encrypt_aes_128_cbc(desired_plaintext, &key[..], &key[..]); @@ -474,51 +516,65 @@ pub fn crack_cbc_iv_key<F1, F2> (encrypt: &F1, verify: &F2) -> Vec<u8> where F1: } } -pub fn crack_sha1_mac_length_extension (input: &[u8], mac: [u8; 20], extension: &[u8]) -> Vec<(Vec<u8>, [u8; 20])> { - let mut sha1_state: [u32; 5] = unsafe { ::std::mem::transmute(mac) }; +pub fn crack_sha1_mac_length_extension( + input: &[u8], + mac: [u8; 20], + extension: &[u8], +) -> Vec<(Vec<u8>, [u8; 20])> { + let mut sha1_state: [u32; 5] = unsafe { std::mem::transmute(mac) }; for word in sha1_state.iter_mut() { *word = u32::from_be(*word); } - (0..100).map(|i| { - let new_input: Vec<u8> = input - .iter() - .chain(::sha1::sha1_padding(i + input.len() as u64).iter()) - .chain(extension.iter()) - .map(|x| *x) - .collect(); - let new_hash = ::sha1::sha1_with_state( - extension, - sha1_state, - i + new_input.len() as u64 - ); - (new_input, new_hash) - }).collect() + (0..100) + .map(|i| { + let new_input: Vec<u8> = input + .iter() + .chain( + crate::sha1::sha1_padding(i + input.len() as u64).iter(), + ) + .chain(extension.iter()) + .map(|x| *x) + .collect(); + let new_hash = crate::sha1::sha1_with_state( + extension, + sha1_state, + i + new_input.len() as u64, + ); + (new_input, new_hash) + }) + .collect() } -pub fn crack_md4_mac_length_extension (input: &[u8], mac: [u8; 16], extension: &[u8]) -> Vec<(Vec<u8>, [u8; 16])> { - let mut md4_state: [u32; 4] = unsafe { ::std::mem::transmute(mac) }; +pub fn crack_md4_mac_length_extension( + input: &[u8], + mac: [u8; 16], + extension: &[u8], +) -> Vec<(Vec<u8>, [u8; 16])> { + let mut md4_state: [u32; 4] = unsafe { std::mem::transmute(mac) }; for word in md4_state.iter_mut() { *word = u32::from_le(*word); } - (0..100).map(|i| { - let new_input: Vec<u8> = input - .iter() - .chain(::md4::md4_padding(i + input.len() as u64).iter()) - .chain(extension.iter()) - .map(|x| *x) - .collect(); - let new_hash = ::md4::md4_with_state( - extension, - md4_state, - i + new_input.len() as u64 - ); - (new_input, new_hash) - }).collect() + (0..100) + .map(|i| { + let new_input: Vec<u8> = input + .iter() + .chain(crate::md4::md4_padding(i + input.len() as u64).iter()) + .chain(extension.iter()) + .map(|x| *x) + .collect(); + let new_hash = crate::md4::md4_with_state( + extension, + md4_state, + i + new_input.len() as u64, + ); + (new_input, new_hash) + }) + .collect() } -fn crack_single_byte_xor_with_confidence (input: &[u8]) -> (u8, f64) { +fn crack_single_byte_xor_with_confidence(input: &[u8]) -> (u8, f64) { let mut min_diff = 100.0; let mut best_key = 0; for a in 0..256u16 { @@ -526,12 +582,15 @@ fn crack_single_byte_xor_with_confidence (input: &[u8]) -> (u8, f64) { input, &::std::iter::repeat(a as u8) .take(input.len()) - .collect::<Vec<u8>>()[..] + .collect::<Vec<u8>>()[..], ); if !decrypted.is_ascii() { continue; } - if decrypted.iter().any(|&c| c != b'\n' && (c < 0x20 || c > 0x7E)) { + if decrypted + .iter() + .any(|&c| c != b'\n' && (c < 0x20 || c > 0x7E)) + { continue; } let lowercase = decrypted.to_ascii_lowercase(); @@ -542,15 +601,17 @@ fn crack_single_byte_xor_with_confidence (input: &[u8]) -> (u8, f64) { total_frequency += 1; if c >= 0x61 && c <= 0x7A { frequencies[(c - 0x61) as usize] += 1; - } - else { + } else { extra_frequencies += 1; } } let mut total_diff = 0.0; - for (&english, &crypt) in ENGLISH_FREQUENCIES.iter().zip(frequencies.iter()) { - let relative_frequency = (crypt as f64) / (total_frequency as f64); + for (&english, &crypt) in + ENGLISH_FREQUENCIES.iter().zip(frequencies.iter()) + { + let relative_frequency = + (crypt as f64) / (total_frequency as f64); total_diff += (english - relative_frequency).abs(); } total_diff += (extra_frequencies as f64) / (total_frequency as f64); @@ -564,7 +625,10 @@ fn crack_single_byte_xor_with_confidence (input: &[u8]) -> (u8, f64) { return (best_key, min_diff); } -fn crack_repeating_key_xor_with_keysize (input: &[u8], keysize: usize) -> (Vec<u8>, f64) { +fn crack_repeating_key_xor_with_keysize( + input: &[u8], + keysize: usize, +) -> (Vec<u8>, f64) { let strides: Vec<Vec<u8>> = (0..keysize) .map(|n| { // XXX sigh ): @@ -585,14 +649,11 @@ fn crack_repeating_key_xor_with_keysize (input: &[u8], keysize: usize) -> (Vec<u .iter() .map(|&(_, diff)| diff) .fold(0.0, |acc, x| acc + x); - let key = cracked - .iter() - .map(|&(c, _)| c) - .collect(); + let key = cracked.iter().map(|&(c, _)| c).collect(); return (key, diff / (keysize as f64)); } -fn count_duplicate_blocks (input: &[u8], block_size: usize) -> usize { +fn count_duplicate_blocks(input: &[u8], block_size: usize) -> usize { let mut set = HashSet::new(); let mut dups = 0; for block in input.chunks(block_size) { @@ -603,26 +664,27 @@ fn count_duplicate_blocks (input: &[u8], block_size: usize) -> usize { return dups; } -fn find_block_size<F> (f: &F) -> usize where F: Fn(&[u8]) -> Vec<u8> { +fn find_block_size<F>(f: &F) -> usize +where + F: Fn(&[u8]) -> Vec<u8>, +{ let (block_size, _) = find_block_size_and_fixed_prefix_len(f); return block_size; } -fn find_block_size_and_fixed_prefix_len<F> (f: &F) -> (usize, usize) where F: Fn(&[u8]) -> Vec<u8> { +fn find_block_size_and_fixed_prefix_len<F>(f: &F) -> (usize, usize) +where + F: Fn(&[u8]) -> Vec<u8>, +{ let fixed_prefix_len = find_fixed_block_prefix_len(f); let byte = b'A'; let mut prev = f(&[b'f']); let mut len = 0; loop { - let prefix: Vec<u8> = ::std::iter::repeat(byte) - .take(len) - .collect(); + let prefix: Vec<u8> = std::iter::repeat(byte).take(len).collect(); let next = f(&prefix[..]); - let prefix_len = shared_prefix_len( - prev.iter(), - next.iter() - ); + let prefix_len = shared_prefix_len(prev.iter(), next.iter()); if prefix_len > fixed_prefix_len { let block_size = prefix_len - fixed_prefix_len; return (block_size, fixed_prefix_len + block_size - (len - 1)); @@ -633,15 +695,19 @@ fn find_block_size_and_fixed_prefix_len<F> (f: &F) -> (usize, usize) where F: Fn } } -fn find_fixed_block_prefix_len<F> (f: &F) -> usize where F: Fn(&[u8]) -> Vec<u8> { +fn find_fixed_block_prefix_len<F>(f: &F) -> usize +where + F: Fn(&[u8]) -> Vec<u8>, +{ let ciphertext1 = f(b""); let ciphertext2 = f(b"A"); return shared_prefix_len(ciphertext1.iter(), ciphertext2.iter()); } -fn shared_prefix_len<I> (i1: I, i2: I) -> usize where I: Iterator, <I as Iterator>::Item: PartialEq { - return i1 - .zip(i2) - .take_while(|&(ref c1, ref c2)| { c1 == c2 }) - .count(); +fn shared_prefix_len<I>(i1: I, i2: I) -> usize +where + I: Iterator, + <I as Iterator>::Item: PartialEq, +{ + return i1.zip(i2).take_while(|&(ref c1, ref c2)| c1 == c2).count(); } |