cryptopals

Matasano's cryptopals challenges (cryptopals.com).
Log | Files | Refs | README | LICENSE

commit 8ef598d54a7b3b9ae04886f1676f4267975c7238
parent b624127d8ab1e425ea865732ab989cab0613fc16
Author: Jared Tobin <jared@jtobin.ca>
Date:   Sun,  3 Sep 2017 22:50:23 +1200

Misc updates.

Diffstat:
Msrc/s2c11.rs | 21+++++++++++++++++++--
Msrc/s2c12.rs | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 120 insertions(+), 32 deletions(-)

diff --git a/src/s2c11.rs b/src/s2c11.rs @@ -69,6 +69,23 @@ pub fn ecb_detector(ciphertext: &[u8], size: usize) -> bool { false } +pub fn ecb_oracle<F>(f: F, size: usize) -> bool + where F: Fn(&[u8]) -> Vec<u8> { + + let blocks = 6; + + let mut buffer = Vec::with_capacity(size * blocks); + + for _ in 0..blocks { + buffer.extend_from_slice(b"ABRACADABRABRA!!"); + } + + let ciphertext = f(&buffer); + + ecb_detector(&ciphertext, size) +} + + pub fn s2c11() -> String { let message = String::from( "Here I'm just gonna try something crazy and type a bunch of words. @@ -97,9 +114,9 @@ pub fn s2c11() -> String { let ciphertext = black_box_encrypter(message.as_bytes()); if ecb_detector(&ciphertext, BLOCK_SIZE) { - String::from("that's probably ECB-encrypted.") + String::from("the sample message was probably ECB-encrypted.") } else { - String::from("that's probably CBC-encrypted.") + String::from("the sample message was probably CBC-encrypted.") } } diff --git a/src/s2c12.rs b/src/s2c12.rs @@ -1,62 +1,133 @@ extern crate base64; extern crate openssl; +extern crate rand; -use s1c07::aes_128_ecb_crypt; +use s1c07; use s2c09::pad_pkcs7; +use s2c11; use self::openssl::symm::Mode; +use self::rand::{Rng, SeedableRng, StdRng}; +use std::collections::HashMap; const BLOCK_SIZE: usize = 16; -const APPENDER: &str = - "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg\ - aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\ - dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg\ - YnkK"; - -// FIXME (jtobin) -// -// Consider just adjusting the original encryption function such that messages -// are always padded appropriately. -// -pub fn aes_128_ecb_crypt_padding(message: &[u8], key: &[u8]) -> Vec<u8> { - let m_size = message.len() + APPENDER.len(); +pub fn aes_128_ecb_crypt(mode: Mode, message: &[u8], key: &[u8]) -> Vec<u8> { + let m_size = message.len(); let c_size = m_size + BLOCK_SIZE - m_size % BLOCK_SIZE; - let mut ciphertext = Vec::with_capacity(c_size); + let ciphertext = pad_pkcs7(message, c_size); + + s1c07::aes_128_ecb_crypt(mode, key, &ciphertext) +} + +pub fn gen_bytes_from_seed(size: usize, seed: &[usize]) -> Vec<u8> { + let mut rng: StdRng = SeedableRng::from_seed(seed); + let mut buffer = Vec::with_capacity(size); + + for _ in 0..size { + let byte: u8 = rng.gen(); + buffer.push(byte); + } + + buffer +} + +pub fn encryption_oracle(injected: &[u8]) -> Vec<u8> { + let message = base64::decode( + "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg\ + aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\ + dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg\ + YnkK").unwrap(); + + let m_size = injected.len() + message.len(); + + let mut augmented_message = Vec::with_capacity(m_size); + + augmented_message.extend_from_slice(injected); + augmented_message.extend_from_slice(&message); + + let key = gen_bytes_from_seed(BLOCK_SIZE, &[1, 1, 2, 3, 5, 8, 13]); + + aes_128_ecb_crypt(Mode::Encrypt, &augmented_message, &key) +} + +pub fn block_size_oracle<F>(f: F) -> usize + where F: Fn(&[u8]) -> Vec<u8> { - let appender = base64::decode(APPENDER).unwrap(); + let mut input = Vec::new(); + let byte = 'A' as u8; - ciphertext.extend_from_slice(message); - ciphertext.extend_from_slice(&appender); + loop { + input.push(byte); - ciphertext = pad_pkcs7(&ciphertext, c_size); + let ciphertext = f(&input); - aes_128_ecb_crypt(Mode::Encrypt, key, &ciphertext) + if ciphertext.len() > input.len() { + return ciphertext.len() - input.len() + 1; + } + } } -pub fn blocksize_oracle(message: &[u8], key: &[u8]) -> usize { +pub fn padding_oracle<F>(f: F) -> usize + where F: Fn(&[u8]) -> Vec<u8> { + let mut input = Vec::new(); - let head = message[0]; + + let ciphertext = f(&input); + let c_size = ciphertext.len(); + + let byte = 'A' as u8; loop { - input.push(head); + input.push(byte); - let ciphertext = aes_128_ecb_crypt_padding(&message, &key); + let new_ciphertext = f(&input); - if ciphertext.len() > message.len() { - return ciphertext.len() - message.len(); + + if new_ciphertext.len() > c_size { + return input.len(); } } } +// pub fn single_byte_ecb_decrypt<F>(f: F) -> Vec<u8> +// where f: Fn(&[u8]) -> Vec<u8> { +// +// let b_size = block_size_oracle(f); +// let is_ecb = s2c11:ecb_oracle(f, b_size); +// +// if !is_ecb { +// panic!("block cipher doesn't use ECB mode."); +// } +// +// let message = vec!['A' as u8; b_size - 1]; +// +// let ciphertext = encryption_oracle(&message); +// +// let temp = ciphertext.take(b_size); +// +// let mut index = HashMap::new(); +// +// let foo = for byte in 0..256 { +// let mut input = message.clone(); +// input.push(byte); +// +// let encrypted = encryption_oracle(&input); +// index.insert(byte, encrypted); +// }; +// } + pub fn s2c12() -> String { + let tester = b"hurbitty gurbitty"; + let key = b"YELLOW SUBMARINE"; + + let black_box = |msg: &[u8]| aes_128_ecb_crypt(Mode::Encrypt, msg, key); - let tester = String::from("hurbitty gurbitty"); - let key = String::from("YELLOW SUBMARINE"); - let foo = blocksize_oracle(&tester.as_bytes(), &key.as_bytes()); + let bsize = block_size_oracle(&black_box); + let padding = padding_oracle(&black_box); + let ecb = s2c11::ecb_oracle(black_box, bsize); - println!("{}", foo); String::from("foo") }