commit b624127d8ab1e425ea865732ab989cab0613fc16
parent d413c86de35859b6f555a1b10c81a6cf5f1b2e00
Author: Jared Tobin <jared@jtobin.ca>
Date: Sat, 2 Sep 2017 14:36:33 +1200
Misc cleanup.
Diffstat:
10 files changed, 123 insertions(+), 108 deletions(-)
diff --git a/src/errors.rs b/src/errors.rs
@@ -4,15 +4,20 @@ extern crate hex;
use std::error;
use std::fmt;
use std::process;
+use std::string;
pub enum CryptopalsError {
- HexConversionError(hex::FromHexError)
+ HexConversionError(hex::FromHexError),
+ Utf8ConversionError(string::FromUtf8Error)
}
impl fmt::Display for CryptopalsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CryptopalsError::HexConversionError(ref err) =>
+ fmt::Display::fmt(err, f),
+
+ CryptopalsError::Utf8ConversionError(ref err) =>
fmt::Display::fmt(err, f)
}
}
@@ -21,13 +26,15 @@ impl fmt::Display for CryptopalsError {
impl error::Error for CryptopalsError {
fn description(&self) -> &str {
match *self {
- CryptopalsError::HexConversionError(ref err) => err.description()
+ CryptopalsError::HexConversionError(ref err) => err.description(),
+ CryptopalsError::Utf8ConversionError(ref err) => err.description()
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
- CryptopalsError::HexConversionError(ref err) => Some(err)
+ CryptopalsError::HexConversionError(ref err) => Some(err),
+ CryptopalsError::Utf8ConversionError(ref err) => Some(err)
}
}
}
@@ -36,6 +43,9 @@ impl fmt::Debug for CryptopalsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CryptopalsError::HexConversionError(ref err) =>
+ fmt::Debug::fmt(err, f),
+
+ CryptopalsError::Utf8ConversionError(ref err) =>
fmt::Debug::fmt(err, f)
}
}
diff --git a/src/main.rs b/src/main.rs
@@ -13,8 +13,8 @@ mod errors;
fn main() {
println!("s1c01:\n{}\n", errors::handle(s1c01::s1c01()));
- println!("s1c02:\n{}\n", s1c02::s1c02());
- println!("s1c03:\n{}\n", s1c03::s1c03());
+ 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());
diff --git a/src/s1c01.rs b/src/s1c01.rs
@@ -3,8 +3,7 @@ extern crate base64;
extern crate hex;
use errors::CryptopalsError;
-use self::hex::{FromHex, FromHexError};
-use std::process;
+use self::hex::FromHex;
const INPUT: &str =
"49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6\
diff --git a/src/s1c02.rs b/src/s1c02.rs
@@ -1,20 +1,35 @@
extern crate hex;
+use errors::CryptopalsError;
use self::hex::{FromHex, ToHex};
const TARGET: &str = "1c0111001f010100061a024b53535009181c";
const PARTNER: &str = "686974207468652062756c6c277320657965";
-fn fixed_xor(target: &str, partner: &str) -> String {
- let mut l: Vec<u8> = FromHex::from_hex(&target).unwrap();
- let r: Vec<u8> = FromHex::from_hex(&partner).unwrap();
+pub fn fixed_xor(target: &[u8], partner: &[u8]) -> Vec<u8> {
+ target.iter()
+ .zip(partner)
+ .map(|(l, r)| l ^ r)
+ .collect()
+}
- for (lb, rb) in l.iter_mut().zip(r) { *lb ^= rb }
+pub fn s1c02() -> Result<String, CryptopalsError> {
+ let target: Result<Vec<u8>, _> = FromHex::from_hex(&TARGET)
+ .map_err(|err| CryptopalsError::HexConversionError(err));
- l.to_hex()
-}
+ let target = match target {
+ Ok(val) => val,
+ Err(err) => return Err(err)
+ };
+
+ let partner: Result<Vec<u8>, _> = FromHex::from_hex(&PARTNER)
+ .map_err(|err| CryptopalsError::HexConversionError(err));
+
+ let partner = match partner {
+ Ok(val) => val,
+ Err(err) => return Err(err)
+ };
-pub fn s1c02() -> String {
- fixed_xor(&TARGET, &PARTNER)
+ Ok(fixed_xor(&target, &partner).to_hex())
}
diff --git a/src/s1c03.rs b/src/s1c03.rs
@@ -1,7 +1,7 @@
extern crate hex;
-use self::hex::{FromHex, ToHex};
+use errors::CryptopalsError;
use std::collections::HashMap;
use std::f32;
use std::u8;
@@ -148,7 +148,10 @@ fn mse(reference: HashMap<u8, f32>, target: HashMap<u8, f32>) -> f32 {
for (key, val) in reference.iter() {
if target.contains_key(key) {
- // (jtobin) branch is only entered if 'target' contains 'key'
+ // NB. (jtobin)
+ //
+ // Branch is only entered if 'target' contains 'key', so 'unwrap'
+ // can't be called.
let tval = target.get(key).unwrap();
let sqdiff = (tval - val).powf(2.0);
result.insert(key, sqdiff);
@@ -160,36 +163,41 @@ fn mse(reference: HashMap<u8, f32>, target: HashMap<u8, f32>) -> f32 {
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)
+fn score(input: &[u8]) -> f32 {
+ mse(freqs_ascii(), frequency_distribution(input.to_vec()))
}
-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);
+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 mut other_bytes = bytes.clone();
-
- for byte in other_bytes.iter_mut() {
- *byte ^= ascii_char;
- }
+ let xored: Vec<u8> = bytes.iter()
+ .map(|byte| byte ^ ascii_char)
+ .collect();
- let decoded = String::from_utf8(other_bytes).unwrap();
- let encoded = ToHex::to_hex(&decoded.clone());
- let result = score(&encoded);
+ let result = score(&xored);
- if result < min.2 { min = (decoded, ascii_char, result); }
+ if result < min.2 {
+ min = (xored, ascii_char, result);
+ }
}
(min.1, min.0)
}
-pub fn s1c03() -> String {
- break_single_byte_xor(INPUT).1
+pub fn s1c03() -> Result<String, CryptopalsError> {
+ let ciphertext: Result<Vec<u8>, CryptopalsError> =
+ hex::FromHex::from_hex(INPUT)
+ .map_err(|err| CryptopalsError::HexConversionError(err));
+
+ let ciphertext = match ciphertext {
+ Ok(val) => val,
+ Err(err) => return Err(err)
+ };
+
+ let message = break_single_byte_xor(&ciphertext).1;
+
+ String::from_utf8(message)
+ .map_err(|err| CryptopalsError::Utf8ConversionError(err))
}
diff --git a/src/s1c07.rs b/src/s1c07.rs
@@ -5,7 +5,6 @@ extern crate openssl;
use self::openssl::symm::{Cipher, Crypter, Mode};
use std::fs::File;
use std::io::prelude::Read;
-use std::str;
use std::string::String;
pub fn new_crypter_unpadded(
@@ -36,42 +35,22 @@ pub fn aes_128_ecb_crypt(mode: Mode, key: &[u8], content: &[u8]) -> Vec<u8> {
buffer[0..crypted_len + finalized_len].to_vec()
}
-pub fn aes_128_ecb_decrypt(key: &str, ciphertext: &str) -> String {
- let key: Vec<u8> = base64::decode(&key).unwrap();
- let ciphertext: Vec<u8> = base64::decode(&ciphertext).unwrap();
-
- let message = aes_128_ecb_crypt(Mode::Decrypt, &key[..], &ciphertext[..]);
-
- base64::encode(&message)
-}
-
-pub fn aes_128_ecb_encrypt(key: &str, message: &str) -> String {
- let key: Vec<u8> = base64::decode(&key).unwrap();
- let message: Vec<u8> = base64::decode(&message).unwrap();
-
- let ciphertext = aes_128_ecb_crypt(Mode::Encrypt, &key[..], &message[..]);
-
- base64::encode(&ciphertext)
-}
-
pub fn s1c07() -> String {
- let key = base64::encode("YELLOW SUBMARINE");
let mut handle = File::open("data/s1/q7_input.txt").unwrap();
let mut buffer = String::new();
- let bsize = handle.read_to_string(&mut buffer);
-
- if let Err(err) = bsize {
- panic!("{}", err);
- }
+ let _ = handle.read_to_string(&mut buffer).unwrap();
- let trimmed: String = buffer.chars()
- .filter(|&char| char != '\n')
+ let ciphertext: String = buffer.chars()
+ .filter(|&c| c != '\n')
.collect();
- let decrypted = aes_128_ecb_decrypt(&key, &trimmed);
- let decrypted = base64::decode(&decrypted).unwrap();
+ let ciphertext = base64::decode(&ciphertext).unwrap();
+
+ let key = b"YELLOW SUBMARINE";
+
+ let message = aes_128_ecb_crypt(Mode::Decrypt, &key[..], &ciphertext);
- String::from_utf8(decrypted).unwrap()
+ String::from_utf8(message).unwrap()
}
diff --git a/src/s2c09.rs b/src/s2c09.rs
@@ -1,7 +1,7 @@
extern crate base64;
-pub fn pkcs(block: &[u8], size: usize) -> Vec<u8> {
+pub fn pad_pkcs7(block: &[u8], size: usize) -> Vec<u8> {
let mut vec = Vec::with_capacity(size);
let len = block.len();
@@ -15,7 +15,7 @@ pub fn pkcs(block: &[u8], size: usize) -> Vec<u8> {
pub fn s2c09() -> String {
let message = "YELLOW_SUBMARINE".as_bytes();
- let padded = pkcs(message, 20);
+ let padded = pad_pkcs7(message, 20);
base64::encode(&padded)
}
diff --git a/src/s2c10.rs b/src/s2c10.rs
@@ -53,31 +53,7 @@ pub fn aes_128_cbc_crypt(
buffer
}
-pub fn aes_128_cbc_decrypt(key: &str, iv: &str, ciphertext: &str) -> String {
- let key: Vec<u8> = base64::decode(&key).unwrap();
- let iv: Vec<u8> = base64::decode(&iv).unwrap();
- let ciphertext: Vec<u8> = base64::decode(&ciphertext).unwrap();
-
- let message =
- aes_128_cbc_crypt(Mode::Decrypt, &key[..], &iv[..], &ciphertext[..]);
-
- base64::encode(&message)
-}
-
-pub fn aes_128_cbc_encrypt(key: &str, iv: &str, message: &str) -> String {
- let key: Vec<u8> = base64::decode(&key).unwrap();
- let iv: Vec<u8> = base64::decode(&iv).unwrap();
- let message: Vec<u8> = base64::decode(&message).unwrap();
-
- let ciphertext =
- aes_128_cbc_crypt(Mode::Encrypt, &key[..], &iv[..], &message[..]);
-
- base64::encode(&ciphertext)
-}
-
-
pub fn s2c10() -> String {
- let key = base64::encode("YELLOW SUBMARINE");
let mut handle = File::open("data/s2/q10_input.txt").unwrap();
let mut buffer = String::new();
@@ -87,16 +63,18 @@ pub fn s2c10() -> String {
panic!("{}", err);
}
- let trimmed: String = buffer.chars()
+ let ciphertext: String = buffer.chars()
.filter(|&char| char != '\n')
.collect();
- let iv = vec![0u8; BLOCK_SIZE];
- let iv = base64::encode(&iv);
+ let ciphertext = base64::decode(&ciphertext).unwrap();
+
+ let key = b"YELLOW SUBMARINE";
+
+ let iv = vec![0u8; BLOCK_SIZE];
- let decrypted = aes_128_cbc_decrypt(&key, &iv, &trimmed);
- let decrypted = base64::decode(&decrypted).unwrap();
+ let message = aes_128_cbc_crypt(Mode::Decrypt, &key[..], &iv, &ciphertext);
- String::from_utf8(decrypted).unwrap()
+ String::from_utf8(message).unwrap()
}
diff --git a/src/s2c11.rs b/src/s2c11.rs
@@ -3,7 +3,7 @@ extern crate rand;
extern crate openssl;
use s1c07::aes_128_ecb_crypt;
-use s2c09::pkcs;
+use s2c09::pad_pkcs7;
use s2c10::aes_128_cbc_crypt;
use self::openssl::symm::Mode;
use self::rand::Rng;
@@ -43,7 +43,7 @@ pub fn black_box_encrypter(message: &[u8]) -> Vec<u8> {
ciphertext.extend_from_slice(message);
ciphertext.extend_from_slice(&append);
- ciphertext = pkcs(&ciphertext, c_size);
+ ciphertext = pad_pkcs7(&ciphertext, c_size);
let key = gen_bytes(KEY_SIZE);
diff --git a/src/s2c12.rs b/src/s2c12.rs
@@ -3,19 +3,23 @@ extern crate base64;
extern crate openssl;
use s1c07::aes_128_ecb_crypt;
-use s2c09::pkcs;
-use s2c11;
+use s2c09::pad_pkcs7;
use self::openssl::symm::Mode;
const BLOCK_SIZE: usize = 16;
const APPENDER: &str =
- "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg
- aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq
- dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg
+ "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg\
+ aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\
+ dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg\
YnkK";
-pub fn mystery_crypter(message: &[u8], key: &[u8]) -> Vec<u8> {
+// 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();
let c_size = m_size + BLOCK_SIZE - m_size % BLOCK_SIZE;
@@ -26,12 +30,34 @@ pub fn mystery_crypter(message: &[u8], key: &[u8]) -> Vec<u8> {
ciphertext.extend_from_slice(message);
ciphertext.extend_from_slice(&appender);
- ciphertext = pkcs(&ciphertext, c_size);
+ ciphertext = pad_pkcs7(&ciphertext, c_size);
aes_128_ecb_crypt(Mode::Encrypt, key, &ciphertext)
}
+pub fn blocksize_oracle(message: &[u8], key: &[u8]) -> usize {
+ let mut input = Vec::new();
+ let head = message[0];
+
+ loop {
+ input.push(head);
+
+ let ciphertext = aes_128_ecb_crypt_padding(&message, &key);
+
+ if ciphertext.len() > message.len() {
+ return ciphertext.len() - message.len();
+ }
+ }
+}
+
pub fn s2c12() -> String {
+
+ let tester = String::from("hurbitty gurbitty");
+ let key = String::from("YELLOW SUBMARINE");
+ let foo = blocksize_oracle(&tester.as_bytes(), &key.as_bytes());
+
+ println!("{}", foo);
+
String::from("foo")
}