Created
May 11, 2017 17:29
-
-
Save gcharnock/29cbe573ef555b23e75ab4cb7fa40e9b to your computer and use it in GitHub Desktop.
My take on getting my head around http://theamazingking.com/crypto-diff.php while also learning some Reust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const SBOX: [u8; 16] = [3, 14, 1, 10, 4, 9, 5, 6, 8, 11, 15, 2, 13, 12, 0, 7]; | |
const INV_SBOX: [u8; 16] = [14, 2, 11, 0, 4, 6, 7, 15, 8, 5, 3, 9, 13, 12, 1, 10]; | |
fn toy_cipher(p: u8, k0: u8, k1: u8) -> u8 { | |
return k1 ^ SBOX[(p ^ k0) as usize]; | |
} | |
fn find_diffs() -> Vec<Vec<Differential>> { | |
println!("Creating XOR differential table:"); | |
let mut diff_table: Vec<Vec<Differential>> = Vec::new(); | |
for d_x in 0..16 { | |
let mut row = Vec::new(); | |
for d_y in 0..16 { | |
row.push(Differential { | |
diff_in: d_x, | |
diff_out: d_y, | |
frequency: 0, | |
pre_sbox_states: Vec::new() | |
}); | |
} | |
diff_table.push(row); | |
} | |
for c in 0..16 { | |
for d in 0..16 { | |
let d_x = c ^ d; | |
let d_y = SBOX[c as usize] ^ SBOX[d as usize]; | |
diff_table[d_x as usize][d_y as usize].frequency+=1; | |
diff_table[d_x as usize][d_y as usize].pre_sbox_states.push(c); | |
} | |
} | |
return diff_table; | |
} | |
struct Differential { | |
diff_in: u8, | |
diff_out: u8, | |
frequency: u8, | |
pre_sbox_states: Vec<u8> | |
} | |
fn find_good_pair(diff_in: u8, diff_out: u8, k1: u8, k2: u8) -> u8 { | |
for p in 0..16 { | |
let c1 = toy_cipher(p, k1, k2); | |
let c2 = toy_cipher(p ^ diff_in, k1, k2); | |
if c1 ^ c2 == diff_out { | |
return p; | |
} | |
} | |
panic!("Could not find good pair"); | |
} | |
fn main() { | |
let k1 = 7; | |
let k2 = 8; | |
let plaintext = 0; | |
let ciphertext = toy_cipher(plaintext, k1, k2); | |
println!("ciphertext = {}", ciphertext); | |
let diff_table = find_diffs(); | |
for c in 1..16 { | |
for d in 1..16 { | |
print!(" {} ", diff_table[c as usize][d as usize].frequency); | |
} | |
println!(""); | |
} | |
println!("Displaying most probable differentials:"); | |
let mut diff_list: Vec<&Differential> = Vec::new(); | |
for d_x in 1..16 { | |
for d_y in 1..16 { | |
diff_list.push(&diff_table[d_x][d_y]); | |
} | |
} | |
diff_list.sort_by_key(|a| 16 - a.frequency); | |
for c in 0..256 { | |
if diff_list[c].frequency < 4 { | |
break; | |
} | |
println!(" {}/16: {} --> {} ", diff_list[c].frequency, diff_list[c].diff_in, diff_list[c].diff_out); | |
} | |
println!("Trying to find a good pair"); | |
let characteristic = diff_list[0]; | |
let good_pair = find_good_pair(characteristic.diff_in, characteristic.diff_out, k1, k2); | |
println!("Found good pair ({}, {})", good_pair, good_pair ^ characteristic.diff_in); | |
println!("The internal state of the cipher past the XOR op must be one of:"); | |
println!("{:?}", characteristic.pre_sbox_states); | |
let possible_k0 = characteristic.pre_sbox_states.iter().map(|s| s ^ good_pair).collect::<Vec<u8>>(); | |
println!("Therefore, the possible k0 we need to brute force are {:?}", possible_k0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment