commit e082523b3c72697a90d47b8a4fd30d92401b78a0
parent f3f35c242f9cad7a9550ce9ab21a4ae0f944733e
Author: Jared Tobin <jared@jtobin.ca>
Date: Thu, 31 Aug 2017 16:47:39 +1200
Renames.
Diffstat:
14 files changed, 352 insertions(+), 350 deletions(-)
diff --git a/docs/s2.md b/docs/s2.md
@@ -63,5 +63,7 @@ and then make the guess:
that's probably CBC-encrypted.
In any case, it's not exactly easy to repeat without actually writing a script.
-Check out [the Rust source](../src/s1c11.rs) to see a sane version.
+Check out [the Rust source][src] to see a sane version.
+
+[src]: https://github.com/jtobin/cryptopals/blob/master/src/s2c11.rs
diff --git a/src/main.rs b/src/main.rs
@@ -1,19 +1,19 @@
-mod s1c1;
-mod s1c2;
-mod s1c3;
-mod s1c7;
+mod s1c01;
+mod s1c02;
+mod s1c03;
+mod s1c07;
-mod s2c9;
+mod s2c09;
mod s2c10;
mod s2c11;
fn main() {
- println!("s1c1:\n{}\n", s1c1::s1c1());
- println!("s1c2:\n{}\n", s1c2::s1c2());
- println!("s1c3:\n{}\n", s1c3::s1c3());
- println!("s1c7:\n{}\n", s1c7::s1c7());
- println!("s2c9:\n{}\n", s2c9::s2c9());
+ println!("s1c01:\n{}\n", s1c01::s1c01());
+ println!("s1c02:\n{}\n", s1c02::s1c02());
+ println!("s1c03:\n{}\n", 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());
}
diff --git a/src/s1c01.rs b/src/s1c01.rs
@@ -0,0 +1,23 @@
+
+extern crate base64;
+extern crate hex;
+
+use self::hex::{FromHex, FromHexError};
+use std::process;
+
+const INPUT: &str =
+ "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6\
+ f7573206d757368726f6f6d";
+
+pub fn hex_to_b64(input: &str) -> Result<String, FromHexError> {
+ let raw: Result<Vec<u8>, _> = FromHex::from_hex(&input);
+ raw.map(|contents| base64::encode(&contents))
+}
+
+pub fn s1c01() -> String {
+ hex_to_b64(&INPUT).unwrap_or_else(|err| {
+ println!("error (cryptopals): {}", err);
+ process::exit(1);
+ })
+}
+
diff --git a/src/s1c02.rs b/src/s1c02.rs
@@ -0,0 +1,20 @@
+
+extern crate hex;
+
+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();
+
+ for (lb, rb) in l.iter_mut().zip(r) { *lb ^= rb }
+
+ l.to_hex()
+}
+
+pub fn s1c02() -> String {
+ fixed_xor(&TARGET, &PARTNER)
+}
diff --git a/src/s1c03.rs b/src/s1c03.rs
@@ -0,0 +1,195 @@
+
+extern crate hex;
+
+use self::hex::{FromHex, ToHex};
+use std::collections::HashMap;
+use std::f32;
+use std::u8;
+
+const INPUT: &'static str =
+ "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
+
+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)
+}
+
+pub fn s1c03() -> String {
+ break_single_byte_xor(INPUT).1
+}
+
diff --git a/src/s1c07.rs b/src/s1c07.rs
@@ -0,0 +1,77 @@
+
+extern crate base64;
+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(
+ 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 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 trimmed: String = buffer.chars()
+ .filter(|&char| char != '\n')
+ .collect();
+
+ let decrypted = aes_128_ecb_decrypt(&key, &trimmed);
+ let decrypted = base64::decode(&decrypted).unwrap();
+
+ String::from_utf8(decrypted).unwrap()
+}
+
diff --git a/src/s1c1.rs b/src/s1c1.rs
@@ -1,23 +0,0 @@
-
-extern crate base64;
-extern crate hex;
-
-use self::hex::{FromHex, FromHexError};
-use std::process;
-
-const INPUT: &str =
- "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6\
- f7573206d757368726f6f6d";
-
-pub fn hex_to_b64(input: &str) -> Result<String, FromHexError> {
- let raw: Result<Vec<u8>, _> = FromHex::from_hex(&input);
- raw.map(|contents| base64::encode(&contents))
-}
-
-pub fn s1c1() -> String {
- hex_to_b64(&INPUT).unwrap_or_else(|err| {
- println!("error (cryptopals): {}", err);
- process::exit(1);
- })
-}
-
diff --git a/src/s1c2.rs b/src/s1c2.rs
@@ -1,20 +0,0 @@
-
-extern crate hex;
-
-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();
-
- for (lb, rb) in l.iter_mut().zip(r) { *lb ^= rb }
-
- l.to_hex()
-}
-
-pub fn s1c2() -> String {
- fixed_xor(&TARGET, &PARTNER)
-}
diff --git a/src/s1c3.rs b/src/s1c3.rs
@@ -1,195 +0,0 @@
-
-extern crate hex;
-
-use self::hex::{FromHex, ToHex};
-use std::collections::HashMap;
-use std::f32;
-use std::u8;
-
-const INPUT: &'static str =
- "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
-
-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)
-}
-
-pub fn s1c3() -> String {
- break_single_byte_xor(INPUT).1
-}
-
diff --git a/src/s1c7.rs b/src/s1c7.rs
@@ -1,77 +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::str;
-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 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 s1c7() -> 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 trimmed: String = buffer.chars()
- .filter(|&char| char != '\n')
- .collect();
-
- let decrypted = aes_128_ecb_decrypt(&key, &trimmed);
- let decrypted = base64::decode(&decrypted).unwrap();
-
- String::from_utf8(decrypted).unwrap()
-}
-
diff --git a/src/s2c09.rs b/src/s2c09.rs
@@ -0,0 +1,21 @@
+
+extern crate base64;
+
+pub fn pkcs(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 = pkcs(message, 20);
+
+ base64::encode(&padded)
+}
diff --git a/src/s2c10.rs b/src/s2c10.rs
@@ -3,7 +3,7 @@ extern crate base64;
extern crate hex;
extern crate openssl;
-use s1c7::aes_128_ecb_crypt;
+use s1c07::aes_128_ecb_crypt;
use std::fs::File;
use self::openssl::symm::Mode;
use std::io::Read;
diff --git a/src/s2c11.rs b/src/s2c11.rs
@@ -2,8 +2,8 @@
extern crate rand;
extern crate openssl;
-use s1c7::aes_128_ecb_crypt;
-use s2c9::pkcs;
+use s1c07::aes_128_ecb_crypt;
+use s2c09::pkcs;
use s2c10::aes_128_cbc_crypt;
use self::openssl::symm::Mode;
use self::rand::Rng;
diff --git a/src/s2c9.rs b/src/s2c9.rs
@@ -1,21 +0,0 @@
-
-extern crate base64;
-
-pub fn pkcs(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 s2c9() -> String {
- let message = "YELLOW_SUBMARINE".as_bytes();
- let padded = pkcs(message, 20);
-
- base64::encode(&padded)
-}