From 5a4924ab99eac6eebbc6941fc07c4cb108316790 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Thu, 27 Apr 2023 20:19:27 -0700 Subject: [PATCH] First half of set 2 --- Cargo.lock | 54 +++++++++++++++++ Cargo.toml | 3 +- examples/set1_7/main.rs | 8 +-- examples/set1_8/main.rs | 10 +--- examples/set2_10/input.txt | 64 ++++++++++++++++++++ examples/set2_10/main.rs | 14 +++++ examples/set2_11/main.rs | 13 +++++ examples/set2_12/main.rs | 91 +++++++++++++++++++++++++++++ examples/set2_9/main.rs | 13 +++++ src/friendly.rs | 85 +++++++++++++++++++++++++++ src/lib.rs | 3 +- src/set2_adversary/mod.rs | 62 ++++++++++++++++++++ src/set2_adversary/nopeeking_12.txt | 4 ++ 13 files changed, 410 insertions(+), 14 deletions(-) create mode 100644 examples/set2_10/input.txt create mode 100644 examples/set2_10/main.rs create mode 100644 examples/set2_11/main.rs create mode 100644 examples/set2_12/main.rs create mode 100644 examples/set2_9/main.rs create mode 100644 src/set2_adversary/mod.rs create mode 100644 src/set2_adversary/nopeeking_12.txt diff --git a/Cargo.lock b/Cargo.lock index 268f3b9..dbb3f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,7 @@ dependencies = [ "aes", "base64", "hex", + "rand", ] [[package]] @@ -73,6 +74,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hex" version = "0.4.3" @@ -94,6 +106,42 @@ version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "typenum" version = "1.16.0" @@ -105,3 +153,9 @@ name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml index 786d6a8..545bdd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] aes = "0.8.2" hex = "0.4" -base64 = "0.21.0" \ No newline at end of file +base64 = "0.21.0" +rand = "0.8.5" diff --git a/examples/set1_7/main.rs b/examples/set1_7/main.rs index b5210db..70a61b1 100644 --- a/examples/set1_7/main.rs +++ b/examples/set1_7/main.rs @@ -1,15 +1,13 @@ #![feature(array_chunks)] -use cryptopals::{prelude::*, bvec64, friendly::aes128}; +use cryptopals::{prelude::*, bvec64, friendly::{aes128, ecb_decrypt, ecb_encrypt}}; fn main() { let key = *b"YELLOW SUBMARINE"; let input = bvec64!("input.txt"); - let mut output = Vec::new(); - for chunk in input.array_chunks::<16>() { - output.extend(aes128::decrypt(key, *chunk)); - } + let output = ecb_decrypt(&input, |block| aes128::decrypt(key, block)); dbg!(output.to_text().unwrap()); + assert_eq!(input, ecb_encrypt(&output, |block| aes128::encrypt(key, block))); println!("pass") } \ No newline at end of file diff --git a/examples/set1_8/main.rs b/examples/set1_8/main.rs index b26dd3a..d117a25 100644 --- a/examples/set1_8/main.rs +++ b/examples/set1_8/main.rs @@ -1,17 +1,13 @@ use cryptopals::bvecs; +use cryptopals::friendly::likely_ecb; use cryptopals::prelude::*; fn main() { let inputs = bvecs!("inputs.txt"); for input in inputs { - 'seek: for ix_0 in (0..input.len()).step_by(16) { - for ix_1 in (ix_0+16..input.len()).step_by(16) { - if input[ix_0..ix_0+16]==input[ix_1..ix_1+16] { - println!("possible ECB: {}", input.to_hex()); - break 'seek - } - } + if likely_ecb(&input) { + println!("possible ECB: {}", input.to_hex()); } } } \ No newline at end of file diff --git a/examples/set2_10/input.txt b/examples/set2_10/input.txt new file mode 100644 index 0000000..0aaafaf --- /dev/null +++ b/examples/set2_10/input.txt @@ -0,0 +1,64 @@ +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 \ No newline at end of file diff --git a/examples/set2_10/main.rs b/examples/set2_10/main.rs new file mode 100644 index 0000000..4bbc873 --- /dev/null +++ b/examples/set2_10/main.rs @@ -0,0 +1,14 @@ +#![feature(array_chunks)] +use cryptopals::{prelude::ByteBased, friendly::{aes128, cbc_decrypt, cbc_encrypt}, bvec64}; + +fn main() { + let input = bvec64!("input.txt"); + let key = *b"YELLOW SUBMARINE"; + let output = cbc_decrypt([0; 16], &input, |block| aes128::decrypt(key, block)); + + let input2 = cbc_encrypt([0; 16], &output, |block| aes128::encrypt(key, block)); + + dbg!(output.to_text().unwrap()); + assert_eq!(input, input2); + println!("pass") +} \ No newline at end of file diff --git a/examples/set2_11/main.rs b/examples/set2_11/main.rs new file mode 100644 index 0000000..d1457b9 --- /dev/null +++ b/examples/set2_11/main.rs @@ -0,0 +1,13 @@ +use cryptopals::{set2_adversary::Set2Adversary, prelude::ByteBased, friendly::likely_ecb}; + +fn main() { + let adversary = Set2Adversary::gen(); + + // blackbox detector + for _ in 0..100 { + let output = adversary.oracle_11(&[b'A'; 64]); + + println!("output: {}", output.to_hex()); + println!("likely ECB: {}", likely_ecb(&output)); + } +} \ No newline at end of file diff --git a/examples/set2_12/main.rs b/examples/set2_12/main.rs new file mode 100644 index 0000000..30aab90 --- /dev/null +++ b/examples/set2_12/main.rs @@ -0,0 +1,91 @@ +use cryptopals::{set2_adversary::Set2Adversary, friendly::likely_ecb, prelude::ByteBased}; + +fn main() { + let adversary = Set2Adversary::gen(); + + // first of all, find the block size + let block_size = { + let mut inp = vec![]; + let l1 = adversary.oracle_12(&inp).len(); + loop { + inp.push(b'A'); + let l2 = adversary.oracle_12(&inp).len(); + if l2 > l1 { + break l2 - l1; + } + } + }; + + assert_eq!(block_size, 16); + + // make sure we're in ECB mode + assert!(likely_ecb(&adversary.oracle_12(&[b'A'; 64]))); + + let message_len = adversary.oracle_12(&[]).len(); + + let mut known_message: Vec = vec![]; + + // sample questions for 'ABCD EFGH' and block size 4 + // question dictionary pattern + // 000 000[A-Z] + // 00 00A[A-Z] + // 0 0AB[A-Z] + // ABC[A-Z] + // 000 BCD[A-Z] + // 00 CDE[A-Z] + // 0 DEF[A-Z] + // EFG[A-Z] + + 'inspect: while known_message.len() < message_len { + let interest_ix = known_message.len(); + + let interest_block_ix= interest_ix / block_size; + let interest_block_byte_ix = interest_ix % block_size; + let interest_shiftr1_padding = (block_size - interest_block_byte_ix - 1) % block_size; // padding it takes to put the character of interest at the end of a block + + // build shiftr + let mut shiftr_block = vec![]; + for _ in 0..interest_shiftr1_padding { shiftr_block.push(0)} + + // build question + // this is the beginning of the dictionary pattern (minus the range at the end) + // if we're at the beginning of the string, use a zero as we know this + // comes from our shiftr block + // otherwise, use a character from the end of the string + let mut question_block = vec![]; + for i in 0..block_size-1 { + let source_char_ix = known_message.len() as i64 - block_size as i64 + i as i64 + 1; + if source_char_ix < 0 { question_block.push(0); } + else { question_block.push(known_message[source_char_ix as usize]); } + } + + // build dictionary + let mut dictionary: Vec> = vec![]; + for possible_byte in u8::MIN..=u8::MAX { + let mut dict_block = question_block.clone(); + dict_block.push(possible_byte); + + let mut oracle_result = adversary.oracle_12(&dict_block); + dictionary.push(oracle_result.drain(0..block_size).collect()) + } + + // now shift the input. we know the position of the block containing the byte of interest + let mut tea_leaves: Vec = adversary.oracle_12(&shiftr_block); + let output_len = tea_leaves.len(); + let block_of_interest: Vec = tea_leaves.drain(interest_block_ix * block_size..interest_block_ix * block_size + block_size).collect(); + + for possible_byte in u8::MIN..=u8::MAX { + if dictionary[possible_byte as usize] == block_of_interest { + if (possible_byte as usize) < block_size && (interest_ix + possible_byte as usize + shiftr_block.len() == output_len) { + break 'inspect // we hit padding + } + known_message.push(possible_byte); + continue 'inspect + } + } + + panic!("we failed to break on padding"); + } + + println!("{}", known_message.to_text().unwrap()) +} \ No newline at end of file diff --git a/examples/set2_9/main.rs b/examples/set2_9/main.rs new file mode 100644 index 0000000..94bd067 --- /dev/null +++ b/examples/set2_9/main.rs @@ -0,0 +1,13 @@ +use cryptopals::friendly::pad_pkcs7; + +fn main() { + assert_eq!( + pad_pkcs7(b"YELLOW SUBMARINE".to_vec(), 20), + b"YELLOW SUBMARINE\x04\x04\x04\x04" + ); + assert_eq!( + pad_pkcs7(b"".to_vec(), 8), + b"\x08\x08\x08\x08\x08\x08\x08\x08" + ); + println!("pass!") +} \ No newline at end of file diff --git a/src/friendly.rs b/src/friendly.rs index df9cd62..b24aa34 100644 --- a/src/friendly.rs +++ b/src/friendly.rs @@ -1,3 +1,74 @@ +use crate::prelude::ByteBased; + +pub fn pad_pkcs7(mut text: Vec, block_size: usize) -> Vec { + assert!(block_size < 256); + let overhang = text.len() % block_size; + let padding = (block_size - overhang) as u8; + + for _ in 0..padding { text.push(padding) } + text +} + +pub fn ecb_encrypt( + plaintext: &[u8], + encrypt_block: impl Fn([u8; N]) -> [u8; N] +) -> Vec { + assert!(plaintext.len() % N == 0); + + let mut ciphertext = vec![]; + + for plaintext_block in plaintext.array_chunks::() { + ciphertext.extend(encrypt_block(*plaintext_block)) + } + + ciphertext +} + +pub fn ecb_decrypt( + ciphertext: &[u8], + decrypt_block: impl Fn([u8; N]) -> [u8; N] +) -> Vec { + // wow! ecb is great + ecb_encrypt(ciphertext, decrypt_block) +} + +pub fn cbc_encrypt( + iv: [u8; N], + plaintext: &[u8], + encrypt_block: impl Fn([u8; N]) -> [u8; N] +) -> Vec { + assert!(plaintext.len() % N == 0); + + let mut ciphertext = vec![]; + + let mut xor_value = iv; + for plaintext_block in plaintext.array_chunks::() { + let ciphertext_block = encrypt_block(plaintext_block.xor_with(&xor_value).unwrap()); + ciphertext.extend(ciphertext_block); + xor_value = ciphertext_block; + }; + return ciphertext +} + +pub fn cbc_decrypt( + iv: [u8; N], + ciphertext: &[u8], + decrypt_block: impl Fn([u8; N]) -> [u8; N] +) -> Vec { + assert!(ciphertext.len() % N == 0); + + let mut plaintext = vec![]; + + let mut xor_value = iv; + for ciphertext_block in ciphertext.array_chunks::() { + let plaintext_block = decrypt_block(*ciphertext_block).xor_with(&xor_value).unwrap(); + plaintext.extend(plaintext_block); + xor_value = *ciphertext_block; + }; + + plaintext +} + pub mod aes128 { use aes::cipher::{generic_array::GenericArray, KeyInit, BlockEncrypt, BlockDecrypt}; @@ -18,4 +89,18 @@ pub mod aes128 { aes.decrypt_block(&mut block); <[u8; 16]>::from(block) } +} + +pub fn likely_ecb(input: &[u8]) -> bool { + assert!(input.len() % 16 == 0); + + // from set1_8 + for ix_0 in (0..input.len()).step_by(16) { + for ix_1 in (ix_0+16..input.len()).step_by(16) { + if input[ix_0..ix_0+16]==input[ix_1..ix_1+16] { + return true + } + } + } + false } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c11d88b..35e131d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![feature(array_chunks)] pub mod friendly; pub mod english; -pub mod prelude; \ No newline at end of file +pub mod prelude; +pub mod set2_adversary; \ No newline at end of file diff --git a/src/set2_adversary/mod.rs b/src/set2_adversary/mod.rs new file mode 100644 index 0000000..13bf6a9 --- /dev/null +++ b/src/set2_adversary/mod.rs @@ -0,0 +1,62 @@ +use rand::Rng; + +use crate::{friendly::{pad_pkcs7, cbc_encrypt, aes128, ecb_encrypt, ecb_decrypt}, bvec64}; +use crate::prelude::*; + +pub struct Set2Adversary { + key: [u8; 16], + secret_12: Vec +} + +impl Set2Adversary { + pub fn gen() -> Self { + let mut key: [u8; 16] = [0; 16]; + rand::thread_rng().fill(&mut key); + + let secret_12 = bvec64!("nopeeking_12.txt"); + + Set2Adversary { key, secret_12 } + } + + pub fn oracle_11(&self, input: &[u8]) -> Vec { + // introduced in challenge 11 + let mut full_input: Vec = vec![]; + let mut rng = rand::thread_rng(); + let count_before = rng.gen_range(5..10); + let count_after = rng.gen_range(5..10); + + for _ in 0..count_before { + full_input.push(rng.gen()) + } + full_input.extend(input); + for _ in 0..count_after { + full_input.push(rng.gen()) + } + + full_input = pad_pkcs7(full_input, 16); + + if rng.gen() { + // ecb + ecb_encrypt(&full_input, |block| aes128::encrypt(self.key, block)) + } else { + // cbc + let mut iv = [0; 16]; + rng.fill(&mut iv); + let message = cbc_encrypt(iv, &full_input, |block| aes128::encrypt(self.key, block)); + + let mut all_ciphertext = vec![]; + all_ciphertext.extend(iv); + all_ciphertext.extend(message); + all_ciphertext + } + } + + pub fn oracle_12(&self, attacker_prefix: &[u8]) -> Vec { + let mut full_input = vec![]; + full_input.extend(attacker_prefix); + full_input.extend(&self.secret_12); + full_input = pad_pkcs7(full_input, 16); + + ecb_encrypt(&full_input, |block| aes128::encrypt(self.key, block)) + } +} \ No newline at end of file diff --git a/src/set2_adversary/nopeeking_12.txt b/src/set2_adversary/nopeeking_12.txt new file mode 100644 index 0000000..490221d --- /dev/null +++ b/src/set2_adversary/nopeeking_12.txt @@ -0,0 +1,4 @@ +Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg +aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq +dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg +YnkK \ No newline at end of file