cryptopals

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

commit 871241456540aad5ef2854e3a7ce9dd1fc6c871d
parent e193dc3c3c4facfc2ce0f4a3e314836529330c3a
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed, 31 May 2023 12:09:37 +0400

Gimme a fresh start.

Diffstat:
DCargo.toml | 13-------------
Ddata/q12_input.txt | 4----
Dlib/aes_cbc/Cargo.lock | 197-------------------------------------------------------------------------------
Dlib/aes_cbc/Cargo.toml | 10----------
Dlib/aes_cbc/src/main.rs | 157-------------------------------------------------------------------------------
Dlib/aes_ecb/Cargo.lock | 197-------------------------------------------------------------------------------
Dlib/aes_ecb/Cargo.toml | 10----------
Dlib/aes_ecb/src/main.rs | 110-------------------------------------------------------------------------------
Dlib/b642hex/B642Hex.hs | 17-----------------
Dlib/break_single_byte_xor/Cargo.toml | 8--------
Dlib/break_single_byte_xor/src/main.rs | 220-------------------------------------------------------------------------------
Dlib/charfreq/Cargo.lock | 14--------------
Dlib/charfreq/Cargo.toml | 8--------
Dlib/charfreq/src/main.rs | 48------------------------------------------------
Dlib/chunks/Chunks.hs | 34----------------------------------
Dlib/ecb_detector/Cargo.lock | 23-----------------------
Dlib/ecb_detector/Cargo.toml | 8--------
Dlib/ecb_detector/src/main.rs | 41-----------------------------------------
Dlib/fixed_xor/Cargo.lock | 14--------------
Dlib/fixed_xor/Cargo.toml | 8--------
Dlib/fixed_xor/src/main.rs | 32--------------------------------
Dlib/hamming/Hamming.hs | 37-------------------------------------
Dlib/hex2b64/Cargo.lock | 14--------------
Dlib/hex2b64/Cargo.toml | 8--------
Dlib/hex2b64/README.md | 7-------
Dlib/hex2b64/src/main.rs | 19-------------------
Dlib/pkcs/PKCS.hs | 30------------------------------
Dlib/repeating_key_xor/Cargo.lock | 14--------------
Dlib/repeating_key_xor/Cargo.toml | 8--------
Dlib/repeating_key_xor/src/main.rs | 46----------------------------------------------
Dlib/rotate/Rotate.hs | 34----------------------------------
Dlib/score_keysizes/Score.hs | 92-------------------------------------------------------------------------------
Dlib/single_byte_xor/Cargo.lock | 14--------------
Dlib/single_byte_xor/Cargo.toml | 8--------
Dlib/single_byte_xor/src/main.rs | 44--------------------------------------------
Dsrc/errors.rs | 62--------------------------------------------------------------
Dsrc/main.rs | 25-------------------------
Dsrc/s1c01.rs | 25-------------------------
Dsrc/s1c02.rs | 22----------------------
Dsrc/s1c03.rs | 189-------------------------------------------------------------------------------
Dsrc/s1c07.rs | 56--------------------------------------------------------
Dsrc/s2c09.rs | 21---------------------
Dsrc/s2c10.rs | 80-------------------------------------------------------------------------------
Dsrc/s2c11.rs | 122-------------------------------------------------------------------------------
Dsrc/s2c12.rs | 140-------------------------------------------------------------------------------
Dsrc/s2c13.rs | 43-------------------------------------------
46 files changed, 0 insertions(+), 2333 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -1,13 +0,0 @@ -[package] -name = "cryptopals" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] -base64 = "0.10.0" -clap = "2.26" -hex = "0.3.2" -openssl = "0.10" -rand = "0.3" -combine = "2.5" - diff --git a/data/q12_input.txt b/data/q12_input.txt @@ -1,4 +0,0 @@ -Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg -aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq -dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg -YnkK diff --git a/lib/aes_cbc/Cargo.lock b/lib/aes_cbc/Cargo.lock @@ -1,197 +0,0 @@ -[root] -name = "aes_cbc" -version = "0.1.0" -dependencies = [ - "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "atty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clap" -version = "2.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gcc" -version = "0.3.49" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "term_size" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "vec_map" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" -"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" -"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)" = "9be730064c122681712957ba1a9abaf082150be8aaf94526a805d900015b65b9" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" -"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2" -"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/lib/aes_cbc/Cargo.toml b/lib/aes_cbc/Cargo.toml @@ -1,10 +0,0 @@ -[package] -name = "aes_cbc" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -base64 = "~0.5.0" -clap = "2.24.2" -openssl = "0.9.11" diff --git a/lib/aes_cbc/src/main.rs b/lib/aes_cbc/src/main.rs @@ -1,157 +0,0 @@ - -// hat tip to ttaubert/rust-cryptopals for lots of help here - -extern crate base64; -extern crate clap; -extern crate openssl; - -use openssl::symm::{Cipher, Crypter, Mode}; -use std::io::{self, Read}; -use clap::{App, Arg}; - -fn fixed_xor(target: Vec<u8>, partner: Vec<u8>) -> Vec<u8> { - assert_eq!(target.len(), partner.len()); - - target - .iter() - .zip(partner) - .map(|(&l, r)| l ^ r) - .collect() -} - -fn new_crypter_unpadded( - cipher: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]> - ) -> Crypter { - assert!(key.len() == 16); - - let mut crypter = match Crypter::new(cipher, mode, key, iv) { - Ok(val) => val, - Err(err) => panic!("{} - key len {}", err, key.len()) - }; - - crypter.pad(false); - - crypter -} - -fn ecb_128_crypt(mode: Mode, key: &[u8], text: &[u8]) -> Vec<u8> { - assert!(text.len() % 16 == 0); - - let cipher = Cipher::aes_128_ecb(); - let iv = None; - - let mut crypter = new_crypter_unpadded(cipher, mode, key, iv); - let mut result = vec![0; text.len() + cipher.key_len()]; - - let decrypted_len = match crypter.update(&text, result.as_mut_slice()) { - Ok(val) => val, - Err(err) => panic!("{}", err) - }; - - (&result[0..decrypted_len]).to_vec() -} - -fn ecb_128_encrypt(key: &[u8], text: &[u8]) -> Vec<u8> { - ecb_128_crypt(Mode::Encrypt, key, text) -} - -fn ecb_128_decrypt(key: &[u8], text: &[u8]) -> Vec<u8> { - ecb_128_crypt(Mode::Decrypt, key, text) -} - -fn cbc_128_encrypt(key: &[u8], text: &[u8], iv: Vec<u8>) -> Vec<u8> { - assert!(iv.len() == 16); - - let mut iv = iv; - let mut ciphertext = Vec::with_capacity(text.len()); - - for block in text.chunks(16) { - let xored = fixed_xor(iv, block.to_vec()); - let encrypted = ecb_128_encrypt(key, xored.as_slice()); - - ciphertext.extend(encrypted.clone()); - iv = encrypted; - } - - ciphertext -} - -fn cbc_128_decrypt(key: &[u8], text: &[u8], iv: Vec<u8>) -> Vec<u8> { - let mut iv = iv; - let mut plain = Vec::with_capacity(text.len()); - - for block in text.chunks(16) { - let decrypted = ecb_128_decrypt(key, block); - plain.extend(fixed_xor(decrypted, iv)); - - iv = block.to_vec(); - } - - plain -} - -fn main() { - let args = App::new("aes_cbc") - .version("0.1") - .about("AES ECB/CBC tools") - .arg(Arg::with_name("key") - .short("k") - .long("key") - .value_name("KEY") - .takes_value(true) - .required(true)) - .arg(Arg::with_name("mode") - .short("e") - .long("encrypt") - .help("encrypt (instead of decrypt)")) - .arg(Arg::with_name("iv") - .short("i") - .long("iv") - .value_name("INIT") - .takes_value(true) - .help("initial value")) - .get_matches(); - - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer).expect("aes_cbc"); - - let decoded = match base64::decode(&buffer) { - Ok(val) => val, - Err(err) => panic!("{}", err) - }; - - let mode = match args.occurrences_of("mode") { - 0 => Mode::Decrypt, - _ => Mode::Encrypt, - }; - - let key = match args.value_of("key") { - Some(text) => - if text.len() == 16 { - text.as_bytes() - } else { - panic!("invalid key length!"); - }, - None => panic!("no key provided.") - }; - - let iv = match args.value_of("iv") { - Some(text) => text.as_bytes().to_vec(), - None => (&[0u8; 16]).to_vec(), - }; - - let output = match mode { - Mode::Decrypt => cbc_128_decrypt(key, &decoded[..], iv), - Mode::Encrypt => cbc_128_encrypt(key, &decoded[..], iv), - }; - - match mode { - Mode::Decrypt => println!("{}", String::from_utf8_lossy(&output)), - Mode::Encrypt => println!("{}", base64::encode(&output)), - }; -} - diff --git a/lib/aes_ecb/Cargo.lock b/lib/aes_ecb/Cargo.lock @@ -1,197 +0,0 @@ -[root] -name = "aes_ecb" -version = "0.1.0" -dependencies = [ - "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "atty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clap" -version = "2.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gcc" -version = "0.3.46" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "term_size" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "vec_map" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" -"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" -"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "181e3cebba1d663bd92eb90e2da787e10597e027eb00de8d742b260a7850948f" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" -"checksum openssl 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "241bcf67b1bb8d19da97360a925730bdf5b6176d434ab8ded55b4ca632346e3a" -"checksum openssl-sys 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e0fd64cb2fa018ed2e7b2c8d9649114fe5da957c9a67432957f01e5dcc82e9" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/lib/aes_ecb/Cargo.toml b/lib/aes_ecb/Cargo.toml @@ -1,10 +0,0 @@ -[package] -name = "aes_ecb" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -base64 = "~0.5.0" -clap = "2.24.2" -openssl = "0.9.11" diff --git a/lib/aes_ecb/src/main.rs b/lib/aes_ecb/src/main.rs @@ -1,110 +0,0 @@ - -extern crate base64; -extern crate clap; -extern crate openssl; - -use openssl::symm::{Cipher, Crypter, Mode}; -use std::io::{self, Read}; -use clap::{App, Arg}; - -const KEY_SIZE: usize = 16; - -fn crypt(cipher: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]>, - input : Vec<u8>) -> Vec<u8> { - - let result_len = input.len() + cipher.key_len(); - let mut result = vec![0u8; result_len]; - - let mut crypter = new_crypter_unpadded(cipher, mode, key, iv); - - let decrypted_len = match crypter.update(&input, result.as_mut_slice()) { - Ok(val) => val, - Err(err) => panic!("couldn't calculate len: {}", err) - }; - - let return_slice = &result[0..decrypted_len]; - - return_slice.to_vec() -} - -fn new_crypter_unpadded( - cipher: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]> - ) -> Crypter { - - let mut crypter = match Crypter::new(cipher, mode, key, iv) { - Ok(val) => val, - Err(err) => panic!("can't create crypter: {}", err) - }; - - crypter.pad(false); - - crypter -} - -fn main() { - let args = App::new("aes_ecb") - .version("0.1") - .about("AES ECB/CBC tools") - .arg(Arg::with_name("key") - .short("k") - .long("key") - .value_name("KEY") - .takes_value(true) - .required(true)) - .arg(Arg::with_name("mode") - .short("e") - .long("encrypt") - .help("encrypt (instead of decrypt)")) - .arg(Arg::with_name("iv") - .short("i") - .long("iv") - .value_name("INIT") - .takes_value(true) - .help("initial value")) - .get_matches(); - - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer).expect("aes_ecb"); - - let decoded = match base64::decode(&buffer) { - Ok(val) => val, - Err(err) => panic!("can't decode from base64: {}", err) - }; - - let mode = match args.occurrences_of("mode") { - 0 => Mode::Decrypt, - _ => Mode::Encrypt, - }; - - let key = match args.value_of("key") { - Some(text) => - if text.len() == KEY_SIZE { - text.as_bytes() - } else { - panic!("invalid key length!"); - }, - None => panic!("no key provided.") - }; - - let iv = match args.value_of("iv") { - Some(text) => Some(text.as_bytes()), - None => None, - }; - - let cipher = Cipher::aes_128_ecb(); - - let output = crypt(cipher, mode, key, iv, decoded); - - match mode { - Mode::Decrypt => println!("{}", String::from_utf8_lossy(&output)), - Mode::Encrypt => println!("{}", base64::encode(&output)), - }; -} - diff --git a/lib/b642hex/B642Hex.hs b/lib/b642hex/B642Hex.hs @@ -1,17 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} - -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Base64 as B64 -import qualified Data.ByteString.Base16 as B16 -import System.IO - -main :: IO () -main = do - bs <- B.getContents - - let decoded = B64.decodeLenient bs - encoded = B16.encode decoded - - B8.hPutStrLn stdout encoded - diff --git a/lib/break_single_byte_xor/Cargo.toml b/lib/break_single_byte_xor/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "break_single_byte_xor" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] -hex = "0.2.0" -clap = "2.26.0" diff --git a/lib/break_single_byte_xor/src/main.rs b/lib/break_single_byte_xor/src/main.rs @@ -1,220 +0,0 @@ - -extern crate clap; -extern crate hex; - -use clap::{App, Arg}; -use self::hex::{FromHex, ToHex}; -use std::collections::HashMap; -use std::io::{self, Read}; -use std::f32; -use std::u8; - -fn tally(vec: Vec<u8>) -> HashMap<u8, u8> { - let mut hashmap = HashMap::new(); - - for byte in vec { - let count = hashmap.entry(byte).or_insert(0); - *count += 1; - } - - hashmap -} - -fn normalize(hashmap: HashMap<u8, u8>) -> HashMap<u8, f32> { - let total = hashmap.iter().fold(0.0, |sum, (_, val)| sum + *val as f32); - - hashmap.iter() - .map(|(&key, val)| (key, *val as f32 / total)) - .collect() -} - -fn frequency_distribution(vec: Vec<u8>) -> HashMap<u8, f32> { - let tallied = tally(vec); - normalize(tallied) -} - -pub fn freqs_ascii() -> HashMap<u8, f32> { - [ (9, 0.000057) - , (23, 0.000000) - , (32, 0.171662) - , (33, 0.000072) - , (34, 0.002442) - , (35, 0.000179) - , (36, 0.000561) - , (37, 0.000160) - , (38, 0.000226) - , (39, 0.002447) - , (40, 0.002178) - , (41, 0.002233) - , (42, 0.000628) - , (43, 0.000215) - , (44, 0.007384) - , (45, 0.013734) - , (46, 0.015124) - , (47, 0.001549) - , (48, 0.005516) - , (49, 0.004594) - , (50, 0.003322) - , (51, 0.001847) - , (52, 0.001348) - , (53, 0.001663) - , (54, 0.001153) - , (55, 0.001030) - , (56, 0.001054) - , (57, 0.001024) - , (58, 0.004354) - , (59, 0.001214) - , (60, 0.001225) - , (61, 0.000227) - , (62, 0.001242) - , (63, 0.001474) - , (64, 0.000073) - , (65, 0.003132) - , (66, 0.002163) - , (67, 0.003906) - , (68, 0.003151) - , (69, 0.002673) - , (70, 0.001416) - , (71, 0.001876) - , (72, 0.002321) - , (73, 0.003211) - , (74, 0.001726) - , (75, 0.000687) - , (76, 0.001884) - , (77, 0.003529) - , (78, 0.002085) - , (79, 0.001842) - , (80, 0.002614) - , (81, 0.000316) - , (82, 0.002519) - , (83, 0.004003) - , (84, 0.003322) - , (85, 0.000814) - , (86, 0.000892) - , (87, 0.002527) - , (88, 0.000343) - , (89, 0.000304) - , (90, 0.000076) - , (91, 0.000086) - , (92, 0.000016) - , (93, 0.000088) - , (94, 0.000003) - , (95, 0.001159) - , (96, 0.000009) - , (97, 0.051880) - , (98, 0.010195) - , (99, 0.021129) - , (100, 0.025071) - , (101, 0.085771) - , (102, 0.013725) - , (103, 0.015597) - , (104, 0.027444) - , (105, 0.049019) - , (106, 0.000867) - , (107, 0.006753) - , (108, 0.031750) - , (109, 0.016437) - , (110, 0.049701) - , (111, 0.057701) - , (112, 0.015482) - , (113, 0.000747) - , (114, 0.042586) - , (115, 0.043686) - , (116, 0.063700) - , (117, 0.020999) - , (118, 0.008462) - , (119, 0.013034) - , (120, 0.001950) - , (121, 0.011330) - , (122, 0.000596) - , (123, 0.000026) - , (124, 0.000007) - , (125, 0.000026) - , (126, 0.000003) - , (131, 0.000000) - , (149, 0.006410) - , (183, 0.000010) - , (223, 0.000000) - , (226, 0.000000) - , (229, 0.000000) - , (230, 0.000000) - , (237, 0.000000) - ].iter().cloned().collect() -} - -fn mse(reference: HashMap<u8, f32>, target: HashMap<u8, f32>) -> f32 { - let mut result = HashMap::new(); - - for (key, val) in reference.iter() { - if target.contains_key(key) { - - // (jtobin) branch is only entered if 'target' contains 'key' - let tval = target.get(key).unwrap(); - let sqdiff = (tval - val).powf(2.0); - result.insert(key, sqdiff); - } - } - - let size = result.len(); - - result.iter().fold(0.0, |sum, (_, val)| sum + val / size as f32) -} - -fn score(string: &str) -> f32 { - let decoded = FromHex::from_hex(&string).unwrap(); - let freq_dist = frequency_distribution(decoded); - - mse(freqs_ascii(), freq_dist) -} - -pub fn break_single_byte_xor(string: &str) -> (u8, String) { - let bytes: Vec<u8> = FromHex::from_hex(&string).unwrap(); - - let mut min = ("hi!".to_string(), 0, f32::INFINITY); - - for ascii_char in 32..126 { - let mut other_bytes = bytes.clone(); - - for byte in other_bytes.iter_mut() { - *byte ^= ascii_char; - } - - let decoded = String::from_utf8(other_bytes).unwrap(); - let encoded = ToHex::to_hex(&decoded.clone()); - let result = score(&encoded); - - if result < min.2 { min = (decoded, ascii_char, result); } - } - - (min.1, min.0) -} - -fn main() { - let args = App::new("break_single_byte_xor") - .version("0.1.0") - .about("Break single-byte XOR") - .arg(Arg::with_name("return-byte") - .short("r") - .long("return-key") - .help("return encrypting byte")) - .get_matches(); - - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer) - .expect("single_byte_xor: bad input"); - - let return_byte = match args.occurrences_of("return-byte") { - 0 => false, - _ => true, - }; - - let message = break_single_byte_xor(&buffer); - - if return_byte { - println!("{} ({})", message.0 as char, message.0); - } else { - println!("{}", message.1); - } -} - diff --git a/lib/charfreq/Cargo.lock b/lib/charfreq/Cargo.lock @@ -1,14 +0,0 @@ -[root] -name = "charfreq" -version = "0.1.0" -dependencies = [ - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" diff --git a/lib/charfreq/Cargo.toml b/lib/charfreq/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "charfreq" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -rustc-serialize = "0.3.0" diff --git a/lib/charfreq/src/main.rs b/lib/charfreq/src/main.rs @@ -1,48 +0,0 @@ -extern crate rustc_serialize as serialize; - -use serialize::hex::FromHex; -use std::collections::HashMap; -use std::env; -use std::string::String; -use std::vec::Vec; - -fn tally(vec: Vec<u8>) -> HashMap<u8, u8> { - let mut hashmap = HashMap::new(); - - for byte in vec { - let count = hashmap.entry(byte).or_insert(0); - *count += 1; - } - - hashmap -} - -fn main() { - let args: Vec<String> = env::args().collect(); - - if args.len() != 2 { - println!("USAGE: ./charfreq HEX"); - return () - } - - let supplied_string = &args[1]; - let supplied_string_len = supplied_string.len(); - - let decoded = match supplied_string.from_hex() { - Err(err) => panic!("charfreq: {} ({})", err, supplied_string_len), - Ok(val) => val, - }; - - let mut results: Vec<(u8, u8)> = tally(decoded).into_iter().collect(); - results.sort_by(|a, b| b.1.cmp(&a.1)); - - let best: Vec<(u8, u8)> = results.into_iter().take(5).collect(); - - println!("original: {}", &supplied_string); - println!("byte (frequency)"); - println!("----------------"); - for (val, count) in best { - println!("{}: {} (freq: {})", val, val as char, count); - } -} - diff --git a/lib/chunks/Chunks.hs b/lib/chunks/Chunks.hs @@ -1,34 +0,0 @@ -{-# OPTIONS_GHC -Wall #-} -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE OverloadedStrings #-} - -import Control.Error (readMay) -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Base16 as B16 -import System.Environment -import System.IO - --- | Split a bytestring into chunks. -chunks :: Int -> B.ByteString -> [B.ByteString] -chunks size = loop mempty where - loop !acc bs - | B.null bs = reverse acc - | otherwise = case B.splitAt size bs of - (chunk, rest) -> loop (chunk : acc) rest - -main :: IO () -main = do - args <- getArgs - - case args of - (narg:_) -> case readMay narg :: Maybe Int of - Nothing -> hPutStrLn stderr "chunks: invalid keysize" - Just size -> do - hex <- B.getContents - let (bs, _) = B16.decode hex - chunked = chunks size bs - rehexed = fmap B16.encode chunked - mapM_ B8.putStrLn rehexed - - _ -> putStrLn "USAGE: echo FOO | ./chunks KEYSIZE" diff --git a/lib/ecb_detector/Cargo.lock b/lib/ecb_detector/Cargo.lock @@ -1,23 +0,0 @@ -[root] -name = "ecb_detector" -version = "0.1.0" -dependencies = [ - "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byteorder" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" diff --git a/lib/ecb_detector/Cargo.toml b/lib/ecb_detector/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "ecb_detector" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -base64 = "~0.5.0" diff --git a/lib/ecb_detector/src/main.rs b/lib/ecb_detector/src/main.rs @@ -1,41 +0,0 @@ - -extern crate base64; - -use std::collections::HashSet; -use std::io::{self, Read}; - -const KEY_SIZE: usize = 16; - -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 -} - -fn main() { - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer).expect("ecb_decoder"); - - let decoded = match base64::decode(&buffer) { - Ok(val) => val, - Err(err) => panic!("{}", err) - }; - - let ecb = ecb_detector(&decoded[..], KEY_SIZE); - - if ecb { - println!("that's probably ECB-encrypted."); - } else { - println!("that's probably CBC-encrypted."); - } -} - diff --git a/lib/fixed_xor/Cargo.lock b/lib/fixed_xor/Cargo.lock @@ -1,14 +0,0 @@ -[root] -name = "fixed_xor" -version = "0.1.0" -dependencies = [ - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" diff --git a/lib/fixed_xor/Cargo.toml b/lib/fixed_xor/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "fixed_xor" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -rustc-serialize = "0.3.0" diff --git a/lib/fixed_xor/src/main.rs b/lib/fixed_xor/src/main.rs @@ -1,32 +0,0 @@ -extern crate rustc_serialize; - -use rustc_serialize::hex::{ToHex, FromHex}; -use std::env; - -fn fixed_xor(target: &str, partner: &str) -> String { - assert_eq!(target.len(), partner.len()); - - let mut l = target.from_hex().unwrap(); - let r = partner.from_hex().unwrap(); - - for (lb, rb) in l.iter_mut().zip(r) { *lb ^= rb } - - l.to_hex() -} - -fn main() { - let args: Vec<String> = env::args().collect(); - - if args.len() != 3 { - println!("USAGE: ./fixed_xor HEX HEX"); - return () - } - - let left = &args[1]; - let right = &args[2]; - - let result = fixed_xor(left, right); - - println!("{}", result); -} - diff --git a/lib/hamming/Hamming.hs b/lib/hamming/Hamming.hs @@ -1,37 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} - -import Data.Bits -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import System.Environment -import System.Exit -import System.IO - --- | Hamming distance between bytestrings. --- --- Returns Nothing if bytestrings are of unequal length. -distance :: B.ByteString -> B.ByteString -> Maybe Int -distance s0 s1 - | B.length s0 /= B.length s1 = Nothing - | otherwise = Just (foldr alg 0 (B.zip s0 s1)) - where - hamming (a, b) = popCount (xor a b) - alg = (+) . hamming - -main :: IO () -main = do - args <- getArgs - case args of - (s0:s1:_) -> do - let b0 = B8.pack s0 - b1 = B8.pack s1 - mhamming = distance b0 b1 - case mhamming of - Nothing -> do - hPutStrLn stderr "hamming: string lengths unequal" - exitFailure - - Just hamming -> print hamming - - _ -> hPutStrLn stderr "USAGE: ./hamming STRING STRING" - diff --git a/lib/hex2b64/Cargo.lock b/lib/hex2b64/Cargo.lock @@ -1,14 +0,0 @@ -[root] -name = "hex2b64" -version = "0.1.0" -dependencies = [ - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" diff --git a/lib/hex2b64/Cargo.toml b/lib/hex2b64/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "hex2b64" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -rustc-serialize = "0.3.0" diff --git a/lib/hex2b64/README.md b/lib/hex2b64/README.md @@ -1,7 +0,0 @@ -# hex2b64 - -Convert hex-encoded strings to base64-encoded strings. - -``` -$ echo '49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d' | cargo run -``` diff --git a/lib/hex2b64/src/main.rs b/lib/hex2b64/src/main.rs @@ -1,19 +0,0 @@ -extern crate rustc_serialize as serialize; - -use serialize::base64::{self, ToBase64}; -use serialize::hex::FromHex; -use std::io::{self, Read}; - -fn main() { - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer) - .expect("hex2b64: bad input"); - - let result = match buffer.from_hex() { - Err(err) => panic!("hex2b64: {}", err), - Ok(val) => val.to_base64(base64::STANDARD), - }; - - println!("{}", result); -} diff --git a/lib/pkcs/PKCS.hs b/lib/pkcs/PKCS.hs @@ -1,30 +0,0 @@ - -import Control.Error (readMay) -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import GHC.Word -import System.Environment -import System.IO - -main :: IO () -main = do - args <- getArgs - - case args of - (narg:_) -> case readMay narg :: Maybe Int of - Nothing -> hPutStrLn stderr "pkcs: invalid length" - Just padto -> do - bytes <- B.getContents - let len = B.length bytes - npad :: Word8 - npad = fromIntegral $ - if padto < len - then 0 - else padto - len - - padded = B.append bytes (B.replicate (fromIntegral npad) npad) - B8.putStrLn padded - - _ -> putStrLn "USAGE: echo STRING | ./pkcs LENGTH" - - diff --git a/lib/repeating_key_xor/Cargo.lock b/lib/repeating_key_xor/Cargo.lock @@ -1,14 +0,0 @@ -[root] -name = "repeating_key_xor" -version = "0.1.0" -dependencies = [ - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" diff --git a/lib/repeating_key_xor/Cargo.toml b/lib/repeating_key_xor/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "repeating_key_xor" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -rustc-serialize = "0.3.0" diff --git a/lib/repeating_key_xor/src/main.rs b/lib/repeating_key_xor/src/main.rs @@ -1,46 +0,0 @@ -extern crate rustc_serialize as serialize; - -use serialize::hex::{ToHex}; -use std::env; -use std::io::{self, Read}; -use std::string::String; -use std::vec::Vec; - -fn repeating_key_xor(text: &str, key: &str) -> String { - let text_bytes = text.as_bytes(); - let key_bytes = key.as_bytes(); - - let mut xored: Vec<u8> = vec![0; text_bytes.len()]; - - for (idx, val) in text_bytes.iter().enumerate() { - let byte_idx = idx % key_bytes.len(); - xored[idx] = val ^ key_bytes[byte_idx]; - } - - xored.to_hex() -} - -fn main() { - // deal with args - let args: Vec<String> = env::args().collect(); - - if args.len() != 2 { - println!("USAGE: echo FOO | ./repeating_key_xor KEY"); - return () - } - - let supplied_key = &args[1]; - - // deal with stdin - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer) - .expect("repeating_key_xor: bad input"); - - let xored = repeating_key_xor(&buffer, &supplied_key); - - println!("original: \n{}", &buffer); - println!("xored with: {}", supplied_key); - println!("result: \n{}", xored); - -} diff --git a/lib/rotate/Rotate.hs b/lib/rotate/Rotate.hs @@ -1,34 +0,0 @@ -{-# OPTIONS_GHC -Wall #-} -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE OverloadedStrings #-} - -import Control.Error (readMay) -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Base16 as B16 -import System.Environment -import System.IO - --- | Split a bytestring into chunks. -chunks :: Int -> B.ByteString -> [B.ByteString] -chunks size = loop mempty where - loop !acc bs - | B.null bs = reverse acc - | otherwise = case B.splitAt size bs of - (chunk, rest) -> loop (chunk : acc) rest - -main :: IO () -main = do - args <- getArgs - - case args of - (narg:_) -> case readMay narg :: Maybe Int of - Nothing -> hPutStrLn stderr "rotate: invalid keysize" - Just size -> do - hex <- B.getContents - let (bs, _) = B16.decode hex - flipped = B.transpose (chunks size bs) - rehexed = fmap B16.encode flipped - mapM_ B8.putStrLn rehexed - - _ -> putStrLn "USAGE: echo HEX | ./rotate KEYSIZE" diff --git a/lib/score_keysizes/Score.hs b/lib/score_keysizes/Score.hs @@ -1,92 +0,0 @@ -{-# OPTIONS_GHC -Wall #-} -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE OverloadedStrings #-} - -import Control.Error (readMay) -import qualified Control.Foldl as L -import Data.Bits -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Base64 as B64 -import qualified Data.IntPSQ as PSQ -import System.Environment - --- | Hamming distance between bytestrings. --- --- Returns Nothing if bytestrings are of unequal length. -distance :: B.ByteString -> B.ByteString -> Maybe Int -distance s0 s1 - | B.length s0 /= B.length s1 = Nothing - | otherwise = Just (foldr alg 0 (B.zip s0 s1)) - where - hamming a b = popCount (xor a b) - alg = (+) . uncurry hamming - --- | Split a bytestring into chunks. -chunks :: Int -> B.ByteString -> [B.ByteString] -chunks size = loop mempty where - loop !acc bs - | B.null bs = reverse acc - | otherwise = case B.splitAt size bs of - (chunk, rest) -> loop (chunk : acc) rest - --- | Score a keysize applied to a bytestring. -score :: Fractional a => Int -> Int -> B.ByteString -> Maybe a -score nchunks size text = do - let normalize x = fromIntegral x / fromIntegral size - cs = chunks size text - - hammings <- case take nchunks cs of - (initial:rest) -> sequence [distance initial chunk | chunk <- rest] - _ -> Nothing - - let nhammings = fmap normalize hammings - return $ L.fold (L.sum / L.genericLength) nhammings - --- | Score keysizes 2-40 over a given bytestring. -scoreKeysizes :: Int -> B.ByteString -> PSQ.IntPSQ Double () -scoreKeysizes nchunks text = loop PSQ.empty 2 where - plain = B64.decodeLenient text - loop !acc size - | size == 40 = acc - | otherwise = case score nchunks size plain of - Nothing -> acc - Just prio -> - let nacc = PSQ.insert size prio () acc - in loop nacc (succ size) - --- | Return the best (smallest) n keys from a queue, by key. -best :: Ord p => Int -> PSQ.IntPSQ p v -> [(Int, p)] -best = loop mempty where - loop !acc idx queue - | idx <= 0 = reverse acc - | otherwise = case PSQ.minView queue of - Nothing -> reverse acc - Just (key, prio, _, rest) -> - let nacc = (key, prio) : acc - in loop nacc (pred idx) rest - -main :: IO () -main = do - bs <- B8.getContents - args <- getArgs - - case args of - (nchunksarg:narg:_) -> do - let n = case readMay narg :: Maybe Int of - Nothing -> PSQ.size scored - Just val -> val - - nchunks = case readMay nchunksarg :: Maybe Int of - Nothing -> 2 - Just val -> val - - scored = scoreKeysizes nchunks bs - top = best n scored - - render (k, v) = show k ++ ": " ++ show v - - putStrLn "keysize: score" - mapM_ (putStrLn . render) top - - _ -> putStrLn "USAGE: echo BASE64 | ./score_keysizes NUM_CHUNKS NUM_RESULTS" diff --git a/lib/single_byte_xor/Cargo.lock b/lib/single_byte_xor/Cargo.lock @@ -1,14 +0,0 @@ -[root] -name = "single_byte_xor" -version = "0.1.0" -dependencies = [ - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" diff --git a/lib/single_byte_xor/Cargo.toml b/lib/single_byte_xor/Cargo.toml @@ -1,8 +0,0 @@ -[package] -name = "single_byte_xor" -version = "0.1.0" -authors = ["Jared Tobin <jared@jtobin.ca>"] - -[dependencies] - -rustc-serialize = "0.3.0" diff --git a/lib/single_byte_xor/src/main.rs b/lib/single_byte_xor/src/main.rs @@ -1,44 +0,0 @@ -extern crate rustc_serialize as serialize; - -use serialize::hex::{FromHex}; -use std::env; -use std::io::{self, Read}; -use std::string::String; - -fn main() { - // deal with args - let args: Vec<String> = env::args().collect(); - - if args.len() != 2 { - println!("USAGE: echo HEX | ./single_byte_xor BYTE"); - return () - } - - let supplied_string = &args[1]; - let supplied_byte = match supplied_string.parse::<u8>() { - Err(err) => panic!("single_byte_xor: failed parse, {}", err), - Ok(val) => val, - }; - - // deal with stdin - let mut buffer = String::new(); - - io::stdin().read_to_string(&mut buffer) - .expect("single_byte_xor: bad input"); - - let mut decoded = match buffer.from_hex() { - Err(err) => panic!("single_byte_xor: {}", err), - Ok(val) => val, - }; - - for byte in decoded.iter_mut() { *byte ^= supplied_byte; } - - let decrypted = match String::from_utf8(decoded) { - Err(err) => panic!("single_byte_xor: {}", err), - Ok(val) => val, - }; - - println!("original: {}", &buffer); - println!("xored with: {} ({})", supplied_string, supplied_byte as char); - println!("decrypted: {}", decrypted); -} diff --git a/src/errors.rs b/src/errors.rs @@ -1,62 +0,0 @@ - -extern crate hex; - -use std::error; -use std::fmt; -// use std::process; -use std::result; -// use std::string; - -pub type Possibly<T> = result::Result<T, CPError>; - -pub enum CPError { - HexConversion(hex::FromHexError), -// Utf8Conversion(string::FromUtf8Error) -} - -impl fmt::Display for CPError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CPError::HexConversion(ref err) => - fmt::Display::fmt(err, f), - -// CPError::Utf8Conversion(ref err) => -// fmt::Display::fmt(err, f) - } - } -} - -impl error::Error for CPError { - fn description(&self) -> &str { - match *self { - CPError::HexConversion(ref err) => err.description(), -// CPError::Utf8Conversion(ref err) => err.description() - } - } - - fn cause(&self) -> Option<&error::Error> { - match *self { - CPError::HexConversion(ref err) => Some(err), -// CPError::Utf8Conversion(ref err) => Some(err) - } - } -} - -impl fmt::Debug for CPError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CPError::HexConversion(ref err) => - fmt::Debug::fmt(err, f), - -// CPError::Utf8Conversion(ref err) => -// fmt::Debug::fmt(err, f) - } - } -} - -// pub fn handle<A>(input: Result<A, CPError>) -> A { -// input.unwrap_or_else(|err| { -// println!("cryptopals (error):\n {}", err); -// process::exit(1); -// }) -// } diff --git a/src/main.rs b/src/main.rs @@ -1,25 +0,0 @@ - -mod s1c01; -mod s1c02; -mod s1c03; -// mod s1c07; -// -// mod s2c09; -// mod s2c10; -// mod s2c11; -// mod s2c12; -// mod s2c13; - -mod errors; -// -// fn main() { -// println!("s1c01:\n{}\n", errors::handle(s1c01::s1c01())); -// println!("s1c02:\n{}\n", errors::handle(s1c02::s1c02())); -// // println!("s1c03:\n{}\n", errors::handle(s1c03::s1c03())); -// // println!("s1c07:\n{}\n", s1c07::s1c07()); -// // println!("s2c09:\n{}\n", s2c09::s2c09()); -// // println!("s2c10:\n{}\n", s2c10::s2c10()); -// // println!("s2c11:\n{}\n", s2c11::s2c11()); -// // println!("s2c12:\n{}\n", s2c12::s2c12()); -// // println!("s2c13:\n{}\n", s2c13::s2c13()); -// } diff --git a/src/s1c01.rs b/src/s1c01.rs @@ -1,25 +0,0 @@ - -extern crate base64; -extern crate hex; - -use errors::{Possibly, CPError}; - -pub fn hex_to_b64(hex: &str) -> Possibly<String> { - let bytes: Possibly<Vec<u8>> = - hex::decode(&hex) - .map_err(|err| CPError::HexConversion(err)); - - bytes.map(|bs| base64::encode(&bs)) -} - -#[test] -fn test_hex_to_b64() { - const INPUT: &str = "49276d206b696c6c696e6720796f757220627261696e206c696b6\ - 5206120706f69736f6e6f7573206d757368726f6f6d"; - - const OUTPUT: &str = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3Vz\ - IG11c2hyb29t"; - let b64 = hex_to_b64(INPUT).unwrap(); - assert_eq!(OUTPUT, b64); -} - diff --git a/src/s1c02.rs b/src/s1c02.rs @@ -1,22 +0,0 @@ - -extern crate hex; - -const TARGET: &str = "1c0111001f010100061a024b53535009181c"; -const PARTNER: &str = "686974207468652062756c6c277320657965"; - -pub fn fixed_xor(target: &[u8], partner: &[u8]) -> Vec<u8> { - target.iter() - .zip(partner) - .map(|(l, r)| l ^ r) - .collect() -} - -#[test] -fn test_fixed_xor() { - let hex0 = hex::decode(TARGET).unwrap(); - let hex1 = hex::decode(PARTNER).unwrap(); - let xor = fixed_xor(&hex0, &hex1); - let expected = "746865206b696420646f6e277420706c6179"; - assert_eq!(hex::encode(xor), expected) -} - diff --git a/src/s1c03.rs b/src/s1c03.rs @@ -1,189 +0,0 @@ - -extern crate hex; - -use std::collections::HashMap; -use std::f32; -use std::u8; - -fn tally(vec: Vec<u8>) -> HashMap<u8, u8> { - let mut hashmap = HashMap::new(); - - for byte in vec { - let count = hashmap.entry(byte).or_insert(0); - *count += 1; - } - - hashmap -} - -fn normalize(hashmap: HashMap<u8, u8>) -> HashMap<u8, f32> { - let total = hashmap.iter().fold(0.0, |sum, (_, val)| sum + *val as f32); - - hashmap.iter() - .map(|(&key, val)| (key, *val as f32 / total)) - .collect() -} - -fn frequency_distribution(vec: Vec<u8>) -> HashMap<u8, f32> { - let tallied = tally(vec); - normalize(tallied) -} - -pub fn freqs_ascii() -> HashMap<u8, f32> { - [ (9, 0.000057) - , (23, 0.000000) - , (32, 0.171662) - , (33, 0.000072) - , (34, 0.002442) - , (35, 0.000179) - , (36, 0.000561) - , (37, 0.000160) - , (38, 0.000226) - , (39, 0.002447) - , (40, 0.002178) - , (41, 0.002233) - , (42, 0.000628) - , (43, 0.000215) - , (44, 0.007384) - , (45, 0.013734) - , (46, 0.015124) - , (47, 0.001549) - , (48, 0.005516) - , (49, 0.004594) - , (50, 0.003322) - , (51, 0.001847) - , (52, 0.001348) - , (53, 0.001663) - , (54, 0.001153) - , (55, 0.001030) - , (56, 0.001054) - , (57, 0.001024) - , (58, 0.004354) - , (59, 0.001214) - , (60, 0.001225) - , (61, 0.000227) - , (62, 0.001242) - , (63, 0.001474) - , (64, 0.000073) - , (65, 0.003132) - , (66, 0.002163) - , (67, 0.003906) - , (68, 0.003151) - , (69, 0.002673) - , (70, 0.001416) - , (71, 0.001876) - , (72, 0.002321) - , (73, 0.003211) - , (74, 0.001726) - , (75, 0.000687) - , (76, 0.001884) - , (77, 0.003529) - , (78, 0.002085) - , (79, 0.001842) - , (80, 0.002614) - , (81, 0.000316) - , (82, 0.002519) - , (83, 0.004003) - , (84, 0.003322) - , (85, 0.000814) - , (86, 0.000892) - , (87, 0.002527) - , (88, 0.000343) - , (89, 0.000304) - , (90, 0.000076) - , (91, 0.000086) - , (92, 0.000016) - , (93, 0.000088) - , (94, 0.000003) - , (95, 0.001159) - , (96, 0.000009) - , (97, 0.051880) - , (98, 0.010195) - , (99, 0.021129) - , (100, 0.025071) - , (101, 0.085771) - , (102, 0.013725) - , (103, 0.015597) - , (104, 0.027444) - , (105, 0.049019) - , (106, 0.000867) - , (107, 0.006753) - , (108, 0.031750) - , (109, 0.016437) - , (110, 0.049701) - , (111, 0.057701) - , (112, 0.015482) - , (113, 0.000747) - , (114, 0.042586) - , (115, 0.043686) - , (116, 0.063700) - , (117, 0.020999) - , (118, 0.008462) - , (119, 0.013034) - , (120, 0.001950) - , (121, 0.011330) - , (122, 0.000596) - , (123, 0.000026) - , (124, 0.000007) - , (125, 0.000026) - , (126, 0.000003) - , (131, 0.000000) - , (149, 0.006410) - , (183, 0.000010) - , (223, 0.000000) - , (226, 0.000000) - , (229, 0.000000) - , (230, 0.000000) - , (237, 0.000000) - ].iter().cloned().collect() -} - -fn mse(expected: HashMap<u8, f32>, observed: HashMap<u8, f32>) -> f32 { - let mut result = HashMap::new(); - - for (key, val) in expected.iter() { - if observed.contains_key(key) { - let tval = observed.get(key).unwrap(); - let sqdiff = (tval - val).powf(2.0); - result.insert(key, sqdiff); - } - } - - let size = result.len(); - - result.iter().fold(0.0, |sum, (_, val)| sum + val / size as f32) -} - -fn score(input: &[u8]) -> f32 { - mse(freqs_ascii(), frequency_distribution(input.to_vec())) -} - -pub fn break_single_byte_xor(bytes: &[u8]) -> (u8, Vec<u8>) { - let mut min = (Vec::new(), 0, f32::INFINITY); - - for ascii_char in 32..126 { - let xored: Vec<u8> = bytes.iter() - .map(|byte| byte ^ ascii_char) - .collect(); - - let result = score(&xored); - - if result < min.2 { - min = (xored, ascii_char, result); - } - } - - (min.1, min.0) -} - -#[test] -fn test_break_single_byte_xor() { - const INPUT: &'static str = - "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"; - - let ciphertext = hex::decode(INPUT).unwrap(); - let message = break_single_byte_xor(&ciphertext).1; - let output = String::from_utf8(message).unwrap(); - assert_eq!(output, "Cooking MC's like a pound of bacon"); -} - diff --git a/src/s1c07.rs b/src/s1c07.rs @@ -1,56 +0,0 @@ - -extern crate base64; -extern crate openssl; - -use self::openssl::symm::{Cipher, Crypter, Mode}; -use std::fs::File; -use std::io::prelude::Read; -use std::string::String; - -pub fn new_crypter_unpadded( - cipher: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]> - ) -> Crypter { - - let mut crypter = Crypter::new(cipher, mode, key, iv).unwrap(); - - crypter.pad(false); - - crypter -} - -pub fn aes_128_ecb_crypt(mode: Mode, key: &[u8], content: &[u8]) -> Vec<u8> { - let cipher = Cipher::aes_128_ecb(); - let iv = None; - let bsize = content.len() + cipher.key_len(); - let mut buffer = vec![0; bsize]; - - let mut crypter = new_crypter_unpadded(cipher, mode, key, iv); - - let crypted_len = crypter.update(content, &mut buffer).unwrap(); - let finalized_len = crypter.finalize(&mut buffer).unwrap(); - - buffer[0..crypted_len + finalized_len].to_vec() -} - -pub fn s1c07() -> String { - let mut handle = File::open("data/s1/q7_input.txt").unwrap(); - let mut buffer = String::new(); - - let _ = handle.read_to_string(&mut buffer).unwrap(); - - let ciphertext: String = buffer.chars() - .filter(|&c| c != '\n') - .collect(); - - let ciphertext = base64::decode(&ciphertext).unwrap(); - - let key = b"YELLOW SUBMARINE"; - - let message = aes_128_ecb_crypt(Mode::Decrypt, &key[..], &ciphertext); - - String::from_utf8(message).unwrap() -} - diff --git a/src/s2c09.rs b/src/s2c09.rs @@ -1,21 +0,0 @@ - -extern crate base64; - -pub fn pad_pkcs7(block: &[u8], size: usize) -> Vec<u8> { - let mut vec = Vec::with_capacity(size); - let len = block.len(); - - let padding_len = if len < size { (size - len) as u8 } else { 0 }; - let padding = vec![padding_len; padding_len as usize ]; - - vec.extend_from_slice(block); - vec.extend_from_slice(&padding); - vec -} - -pub fn s2c09() -> String { - let message = "YELLOW_SUBMARINE".as_bytes(); - let padded = pad_pkcs7(message, 20); - - base64::encode(&padded) -} diff --git a/src/s2c10.rs b/src/s2c10.rs @@ -1,80 +0,0 @@ - -extern crate base64; -extern crate hex; -extern crate openssl; - -use s1c07::aes_128_ecb_crypt; -use std::fs::File; -use self::openssl::symm::Mode; -use std::io::Read; -use std::str; - -const BLOCK_SIZE: usize = 16; - -fn fixed_xor(target: &[u8], partner: &[u8]) -> Vec<u8> { - target.iter() - .zip(partner) - .map(|(l, r)| l ^ r) - .collect() -} - -pub fn aes_128_cbc_crypt( - mode: Mode - , key: &[u8] - , iv: &[u8] - , contents: &[u8] - ) -> Vec<u8> { - - let mut buffer = Vec::with_capacity(contents.len()); - - match mode { - Mode::Encrypt => { - contents.chunks(BLOCK_SIZE).fold(iv.to_vec(), - |i, block| { - let xored = fixed_xor(&i, block); - let encrypted = aes_128_ecb_crypt(mode, key, &xored); - - buffer.extend(&encrypted); - encrypted - }); - }, - Mode::Decrypt => { - contents.chunks(BLOCK_SIZE).fold(iv.to_vec(), - |i, block| { - let decrypted = aes_128_ecb_crypt(mode, key, block); - let xored = fixed_xor(&decrypted, &i); - - buffer.extend(&xored); - block.to_vec() - }); - } - } - - buffer -} - -pub fn s2c10() -> String { - let mut handle = File::open("data/s2/q10_input.txt").unwrap(); - let mut buffer = String::new(); - - let bsize = handle.read_to_string(&mut buffer); - - if let Err(err) = bsize { - panic!("{}", err); - } - - let ciphertext: String = buffer.chars() - .filter(|&char| char != '\n') - .collect(); - - let ciphertext = base64::decode(&ciphertext).unwrap(); - - let key = b"YELLOW SUBMARINE"; - - let iv = vec![0u8; BLOCK_SIZE]; - - let message = aes_128_cbc_crypt(Mode::Decrypt, &key[..], &iv, &ciphertext); - - String::from_utf8(message).unwrap() -} - diff --git a/src/s2c11.rs b/src/s2c11.rs @@ -1,122 +0,0 @@ - -extern crate rand; -extern crate openssl; - -use s1c07::aes_128_ecb_crypt; -use s2c09::pad_pkcs7; -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 _ 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 m_size = prepend_size + message.len() + append_size; - let c_size = m_size + BLOCK_SIZE - m_size % BLOCK_SIZE; - - let mut ciphertext = Vec::with_capacity(c_size); - - ciphertext.extend_from_slice(&prepend); - ciphertext.extend_from_slice(message); - ciphertext.extend_from_slice(&append); - - ciphertext = pad_pkcs7(&ciphertext, c_size); - - let key = gen_bytes(KEY_SIZE); - - if rng.gen() { - aes_128_ecb_crypt(Mode::Encrypt, &key, &ciphertext) - } else { - let iv = gen_bytes(KEY_SIZE); - aes_128_cbc_crypt(Mode::Encrypt, &key, &iv, &ciphertext) - } -} - -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 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"AAAAAAAAAAAAAAAA"); - } - - 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. - 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. - - Hmm that doesn't seem to be doing it though. Somehow. I'll check that - function again in a second, but it seems like the easiest thing to do - might just be to write more text, use some longer words, etc. Maybe - use some longer words again and again, you know. Like sentences. Or - somehow. - - What if I were to just include the same exact text multiple times? - - What if I were to just include the same exact text multiple times? - - I said, what if I were to just include the same exact text multiple - times?"); - - let ciphertext = black_box_encrypter(message.as_bytes()); - - if ecb_detector(&ciphertext, BLOCK_SIZE) { - String::from("the sample message was probably ECB-encrypted.") - } else { - String::from("the sample message was probably CBC-encrypted.") - } -} - diff --git a/src/s2c12.rs b/src/s2c12.rs @@ -1,140 +0,0 @@ - -extern crate base64; -extern crate openssl; -extern crate rand; - -use s1c07; -use s2c09::pad_pkcs7; -use s2c11; -use self::openssl::symm::Mode; -use self::rand::{Rng, SeedableRng, StdRng}; -use std::ops::Range; -use std::iter::{FromIterator, repeat}; - -const BLOCK_SIZE: usize = 16; - -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 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 block_size_oracle<F>(f: F) -> usize - where F: Fn(&[u8]) -> Vec<u8> { - - let mut input = Vec::new(); - let byte = 'A' as u8; - - loop { - input.push(byte); - - let ciphertext = f(&input); - - if ciphertext.len() > input.len() { - return ciphertext.len() - input.len() + 1; - } - } -} - -pub fn padding_oracle<F>(f: F) -> usize - where F: Fn(&[u8]) -> Vec<u8> { - - let mut input = Vec::new(); - - let ciphertext = f(&input); - let c_size = ciphertext.len(); - - let byte = 'A' as u8; - - loop { - input.push(byte); - - let new_ciphertext = f(&input); - - if new_ciphertext.len() > c_size { - return input.len(); - } - } -} - -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) -} - -// lifted this just about verbatim from ttaubert/rust-cryptopals -// his looping method is pretty smahhhhhhhhhht -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); // FIXME - let padding = padding_oracle(&f); - - let ciphertext = f(&[]); - let c_size = ciphertext.len(); - - let mut input = Vec::from_iter(repeat(b'A').take(c_size)); - - let guess = Range { start: c_size - b_size, end: c_size }; - - for index in 0..c_size - padding { - if index % b_size == 0 { - let block = input[guess.clone()].to_vec(); - input.extend(block); - } - - input.remove(0); - - let start = c_size + index - index % b_size; - let target = Range { start: start, end: start + b_size }; - - for byte in 0..256 { - input[c_size - 1] = byte as u8; - let probe = f(&input); - - if probe[guess.clone()] == probe[target.clone()] { - break; - } - } - - } - - input[padding..c_size].to_vec() -} - -pub fn s2c12() -> String { - let message = single_byte_ecb_decrypt(encryption_oracle); - - String::from_utf8(message).unwrap() -} - diff --git a/src/s2c13.rs b/src/s2c13.rs @@ -1,43 +0,0 @@ - -extern crate combine; - -use self::combine::{many1, sep_by, token, none_of}; -// use self::combine::char::letter; - -pub fn foo(input: String) -> String { - let metachars = "&=".iter().cloned(); - let word = many1(none_of(metachars)); - let pair = sep_by(word, token('=')); - let pairs = sep_by(pair, token('&')); - - String::from("hello") -} - - -pub fn s2c13() -> String{ - String::from("foo") -} - - - -// pub fn s2c13() -> String { -// // FIXME & is not right here - there shouldn't be a hanging & -// let structured_cookie = Regex::new(r"([A-Za-z]+=[^&=]*&?)*").unwrap(); -// -// let test = structured_cookie.captures("foo=bar&baz=quux").unwrap(); -// -// println!("{} {}", test.get(0).unwrap().as_str(), test.get(1).unwrap().as_str()); -// -// String::from("foo") -// } - -// -// foo=bar&baz=qux -// -// parse that into some kind of json -// -// { -// 'foo': 'bar', -// 'baz': 'qux' -// } -//