cryptopals

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

commit 44264eeefe86f0d5ffe8088f9a96c2822b9745f9
parent c02b362176501c3b0af17045c93f6aabdd85c66a
Author: Jared Tobin <jared@jtobin.ca>
Date:   Thu, 31 Aug 2017 13:23:22 +1200

Updates.

Diffstat:
MCargo.toml | 7++++---
Mdocs/s2.md | 3++-
Msrc/main.rs | 2++
Asrc/s2c11.rs | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -4,8 +4,9 @@ version = "0.1.0" authors = ["Jared Tobin <jared@jtobin.ca>"] [dependencies] -base64 = "0.6.0" -clap = "2.26.0" -hex = "0.2.0" +base64 = "0.6.0" +clap = "2.26.0" +hex = "0.2.0" openssl = "0.9.11" +rand = "0.3.16" diff --git a/docs/s2.md b/docs/s2.md @@ -64,5 +64,6 @@ and then make the guess: which is actually the wrong one here. -But, uh, let's not use bash for this. +But, uh, let's not use bash for this. Check [the source](../src/s2c11.rs) for +now. diff --git a/src/main.rs b/src/main.rs @@ -5,6 +5,7 @@ mod s1c3; mod s1c7; mod s2c10; +mod s2c11; fn main() { println!("s1c1:\n{}\n", s1c1::s1c1()); @@ -12,4 +13,5 @@ fn main() { println!("s1c3:\n{}\n", s1c3::s1c3()); println!("s1c7:\n{}\n", s1c7::s1c7()); println!("s2c10:\n{}\n", s2c10::s2c10()); + println!("s2c11:\n{}\n", s2c11::s2c11()); } diff --git a/src/s2c11.rs b/src/s2c11.rs @@ -0,0 +1,88 @@ + +extern crate rand; +extern crate openssl; + +use s1c7::aes_128_ecb_crypt; +use s2c10::aes_128_cbc_crypt; +use self::openssl::symm::Mode; +use self::rand::Rng; +use self::rand::distributions::{IndependentSample, Range}; +use std::collections::HashSet; + +const KEY_SIZE: usize = 16; +const BLOCK_SIZE: usize = 16; + +pub fn gen_bytes(size: usize) -> Vec<u8> { + let mut rng = rand::thread_rng(); + let mut buffer = Vec::with_capacity(size); + + for foo in 0..size { + let byte: u8 = rng.gen(); + buffer.push(byte); + } + + buffer +} + +pub fn black_box_encrypter(message: &[u8]) -> Vec<u8> { + let mut rng = rand::thread_rng(); + + let between = Range::new(5, 11); + let prepend_size = between.ind_sample(&mut rng); + let append_size = between.ind_sample(&mut rng); + + let prepend = gen_bytes(prepend_size); + let append = gen_bytes(append_size); + + let ciphertext_size = prepend_size + message.len() + append_size; + let mut ciphertext = Vec::with_capacity(ciphertext_size); + + let key = gen_bytes(KEY_SIZE); + + ciphertext.extend_from_slice(&prepend); + ciphertext.extend_from_slice(message); + ciphertext.extend_from_slice(&append); + + if rng.gen() { + aes_128_ecb_crypt(Mode::Encrypt, &key, &message) + } else { + let iv = gen_bytes(KEY_SIZE); + aes_128_cbc_crypt(Mode::Encrypt, &key, &iv, &message) + } +} + +pub fn ecb_detector(ciphertext: &[u8], size: usize) -> bool { + let mut blocks = HashSet::new(); + + for block in ciphertext.chunks(size) { + if blocks.contains(block) { + return true; + } + + blocks.insert(block); + } + + false +} + +pub fn s2c11() -> String { + let message = String::from( + "Here I'm just gonna try something crazy and type a bunch of words. + Like, enough words so that if I actually give decrypting this a shot, + it has a reasonable chance of detecting ECB when it actually occurs + This is actually more likely than it might initially seem; if the block + size is just 16, so two consecutive characters anywhere in the message + should encrypt to the same thing. Interesting to see if the oracle + will actually be able to bust it on this text. So yeah, anyway, let's + see what happens. At the very least there are a bunch of double spaces + at the end of sentences."); + + let ciphertext = black_box_encrypter(message.as_bytes()); + + if ecb_detector(&ciphertext, BLOCK_SIZE) { + String::from("probably ECB.") + } else { + String::from("probably CBC.") + } +} +