From 08a8cad6f2221171b9c2f466eaeea353baa5fd8e Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Tue, 5 Jul 2022 11:39:35 -0400 Subject: [PATCH] Work on challenge 17. --- src/bytes.rs | 2 +- src/main.rs | 32 ++++++++++++++++---------------- src/set3.rs | 35 +++++++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index ec74ada..9e96aa6 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -101,7 +101,7 @@ impl Bytes { } } - pub fn has_valid_pkcs7(&mut self, block_size: usize) -> bool { + pub fn has_valid_pkcs7(&self, block_size: usize) -> bool { if self.len() > 0 && self.len() % block_size != 0 { return false; } diff --git a/src/main.rs b/src/main.rs index 7534c99..7a89c86 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,21 +8,21 @@ mod set2; mod set3; fn main() { - set1::challenge1(); - set1::challenge2(); - set1::challenge3(); - set1::challenge4(); - set1::challenge5(); - set1::challenge6(); - set1::challenge7(); - set1::challenge8(); - set2::challenge9(); - set2::challenge10(); - set2::challenge11(); - set2::challenge12(); - set2::challenge13(); - set2::challenge14(); - set2::challenge15(); - set2::challenge16(); + // set1::challenge1(); + // set1::challenge2(); + // set1::challenge3(); + // set1::challenge4(); + // set1::challenge5(); + // set1::challenge6(); + // set1::challenge7(); + // set1::challenge8(); + // set2::challenge9(); + // set2::challenge10(); + // set2::challenge11(); + // set2::challenge12(); + // set2::challenge13(); + // set2::challenge14(); + // set2::challenge15(); + // set2::challenge16(); set3::challenge17(); } diff --git a/src/set3.rs b/src/set3.rs index 0158210..2a43aa6 100644 --- a/src/set3.rs +++ b/src/set3.rs @@ -13,10 +13,11 @@ pub fn challenge17() { .collect() } - fn encrypt(ten_strings: &Vec, key: &Bytes) -> (Bytes, Bytes) { + fn encrypt(key: &Bytes) -> (Bytes, Bytes) { // The first function should select at random one of the ten strings - let index: usize = rand::thread_rng().gen_range(0..ten_strings.len()); - let mut cleartext = Bytes(ten_strings[index].0.to_vec()); + let cleartexts = read("data/17.txt"); + let index: usize = rand::thread_rng().gen_range(0..cleartexts.len()); + let mut cleartext = Bytes(cleartexts[index].0.to_vec()); // pad the string out to the 16-byte AES block size and cleartext.pad_pkcs7(16); @@ -26,11 +27,33 @@ pub fn challenge17() { let iv = Bytes::random(16); (cbc::encrypt(&key, &iv, &cleartext), iv) } - let cleartexts = read("data/17.txt"); // generate a random AES key (which it should save for all future encryptions) let key = Bytes::random(16); - let (cipher, _iv) = encrypt(&cleartexts, &key); + let (cipher, _iv) = encrypt(&key); + let decryption_oracle = |iv: &Bytes, cipher: &Bytes| -> bool { + // The second function should consume the ciphertext produced by the + // first function, decrypt it, check its padding, and return true or + // false depending on whether the padding is valid. + let roundtrip = cbc::decrypt(&key, iv, cipher); + roundtrip.has_valid_pkcs7(16) + }; - println!("[xxxx] Challenge 17: {}", cipher.len()); + let attack_block = |cipher_block: &Bytes| -> Bytes { + let block_size = cipher_block.len(); + let mut iv = Bytes::random(block_size); + + for i in 0..=255 { + iv.0[15] = i; + + if decryption_oracle(&iv, cipher_block) { + println!("{i:#016b}"); + } + } + Bytes(vec![]) + }; + + let _block_count = cipher.len() / 16; + let first_block = attack_block(&cipher.get_block(0, 16)); + println!("[xxxx] Challenge 17: {:?}", first_block); }