summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2015-04-06 02:25:18 -0400
committerJesse Luehrs <doy@tozt.net>2015-04-06 02:26:39 -0400
commit2445f1468ec8176e9f36768cb11bc94466b5e671 (patch)
tree21e53a177e3efd9cf677ddc85961afcb2b51b257 /tests
parent3d08e9986ed006cdf1c6f37969c9d11c53918105 (diff)
downloadmatasano-2445f1468ec8176e9f36768cb11bc94466b5e671.tar.gz
matasano-2445f1468ec8176e9f36768cb11bc94466b5e671.zip
split the test code up a bit more
Diffstat (limited to 'tests')
-rw-r--r--tests/lib.rs475
-rw-r--r--tests/set1.rs90
-rw-r--r--tests/set2.rs230
-rw-r--r--tests/set3.rs169
-rw-r--r--tests/util.rs15
5 files changed, 499 insertions, 480 deletions
diff --git a/tests/lib.rs b/tests/lib.rs
deleted file mode 100644
index 0930e64..0000000
--- a/tests/lib.rs
+++ /dev/null
@@ -1,475 +0,0 @@
-extern crate matasano;
-extern crate rustc_serialize as serialize;
-extern crate rand;
-extern crate time;
-
-use std::ascii::AsciiExt;
-use std::borrow::ToOwned;
-use std::collections::HashMap;
-
-use rand::{Rng, SeedableRng};
-use serialize::base64::FromBase64;
-use serialize::hex::FromHex;
-
-mod util;
-
-#[test]
-fn problem_1 () {
- let hex = "49276d206b696c6c696e6720796f757220627261\
- 696e206c696b65206120706f69736f6e6f757320\
- 6d757368726f6f6d".from_hex().unwrap();
- let base64 = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEg\
- cG9pc29ub3VzIG11c2hyb29t";
- let got = matasano::to_base64(&hex[..]);
- assert_eq!(got, base64);
-}
-
-#[test]
-fn problem_2 () {
- let bytes1 = "1c0111001f010100061a024b53535009181c".from_hex().unwrap();
- let bytes2 = "686974207468652062756c6c277320657965".from_hex().unwrap();
- let expected = "746865206b696420646f6e277420706c6179".from_hex().unwrap();
- let got = matasano::fixed_xor(&bytes1[..], &bytes2[..]);
- assert_eq!(got, expected);
-}
-
-#[test]
-fn problem_3 () {
- let ciphertext = "1b37373331363f78151b7f2b783431333d783978\
- 28372d363c78373e783a393b3736".from_hex().unwrap();
- let plaintext = b"Cooking MC's like a pound of bacon";
- let got = matasano::crack_single_byte_xor(&ciphertext[..]);
- assert_eq!(got, &plaintext[..]);
-}
-
-#[test]
-fn problem_4 () {
- let possibles = util::read_as_hex_lines("data/4.txt");
- let plaintext = b"Now that the party is jumping\n";
- let got = matasano::find_single_byte_xor_encrypted_string(&possibles[..]);
- assert_eq!(got, plaintext);
-}
-
-#[test]
-fn problem_5 () {
- let plaintext = b"Burning 'em, if you ain't quick and nimble\n\
- I go crazy when I hear a cymbal";
- let key = b"ICE";
- let ciphertext = "0b3637272a2b2e63622c2e69692a23693a2a3c63\
- 24202d623d63343c2a26226324272765272a282b\
- 2f20430a652e2c652a3124333a653e2b2027630c\
- 692b20283165286326302e27282f".from_hex().unwrap();
- let got = matasano::repeating_key_xor(plaintext, key);
- assert_eq!(got, ciphertext);
-}
-
-#[test]
-fn problem_6 () {
- let ciphertext = util::read_as_base64("data/6.txt");
- let plaintext = util::read("data/6.out.txt");
- let key = matasano::crack_repeating_key_xor(&ciphertext[..]);
- let got = matasano::repeating_key_xor(&ciphertext[..], &key[..]);
- assert_eq!(got, plaintext);
-}
-
-#[test]
-fn problem_7 () {
- let ciphertext = util::read_as_base64("data/7.txt");
- let key = b"YELLOW SUBMARINE";
- let plaintext = util::read("data/7.out.txt");
- let got = matasano::decrypt_aes_128_ecb(&ciphertext[..], key);
- assert_eq!(got, Some(plaintext));
-}
-
-#[test]
-fn problem_8 () {
- let possibles = util::read_as_hex_lines("data/8.txt");
- let ciphertext = "d880619740a8a19b7840a8a31c810a3d08649af7\
- 0dc06f4fd5d2d69c744cd283e2dd052f6b641dbf\
- 9d11b0348542bb5708649af70dc06f4fd5d2d69c\
- 744cd2839475c9dfdbc1d46597949d9c7e82bf5a\
- 08649af70dc06f4fd5d2d69c744cd28397a93eab\
- 8d6aecd566489154789a6b0308649af70dc06f4f\
- d5d2d69c744cd283d403180c98c8f6db1f2a3f9c\
- 4040deb0ab51b29933f2c123c58386b06fba186a"
- .from_hex().unwrap();
- let got = matasano::find_aes_128_ecb_encrypted_string(&possibles[..]);
- assert_eq!(got, ciphertext);
-}
-
-#[test]
-fn problem_9 () {
- let block = b"YELLOW SUBMARINE";
- let got = matasano::pad_pkcs7(block, 20);
- assert_eq!(got, b"YELLOW SUBMARINE\x04\x04\x04\x04");
-}
-
-#[test]
-fn problem_10 () {
- let ciphertext = util::read_as_base64("data/10.txt");
- let key = b"YELLOW SUBMARINE";
- let plaintext = util::read("data/10.out.txt");
- let got = matasano::decrypt_aes_128_cbc(&ciphertext[..], key, &[0; 16]);
- assert_eq!(got, Some(plaintext));
-}
-
-#[test]
-fn problem_11 () {
- static mut last_mode: matasano::BlockCipherMode = matasano::BlockCipherMode::ECB;
-
- fn random_padding (input: &[u8]) -> Vec<u8> {
- let front_padding: Vec<u8> = rand::thread_rng()
- .gen_iter()
- .take(rand::thread_rng().gen_range(5, 10))
- .collect();
- let back_padding: Vec<u8> = rand::thread_rng()
- .gen_iter()
- .take(rand::thread_rng().gen_range(5, 10))
- .collect();
- return front_padding
- .iter()
- .chain(input.iter())
- .chain(back_padding.iter())
- .map(|x| *x)
- .collect()
- }
-
- fn random_encrypter (input: &[u8]) -> Vec<u8> {
- let key = util::random_aes_128_key();
- let padded_input = random_padding(input);
- if util::coinflip() {
- unsafe {
- last_mode = matasano::BlockCipherMode::ECB;
- }
- return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
- }
- else {
- unsafe {
- last_mode = matasano::BlockCipherMode::CBC;
- }
- let iv = util::random_aes_128_key();
- return matasano::encrypt_aes_128_cbc(&padded_input[..], &key[..], &iv[..]);
- }
- }
-
- for _ in 0..100 {
- let got = matasano::detect_ecb_cbc(&random_encrypter, 16);
- let expected = unsafe { &last_mode };
- assert_eq!(&got, expected);
- }
-}
-
-#[test]
-fn problem_12 () {
- let padding = b"Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWct\
- dG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpU\
- aGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\
- dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5v\
- LCBJIGp1c3QgZHJvdmUgYnkK".from_base64().unwrap();
- let fixed_padding = |input: &[u8]| -> Vec<u8> {
- return input
- .iter()
- .chain(padding.iter())
- .map(|x| *x)
- .collect()
- };
-
- let key = util::random_aes_128_key();
- let random_encrypter = |input: &[u8]| {
- let padded_input = fixed_padding(input);
- return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
- };
-
- let got = matasano::crack_padded_aes_128_ecb(&random_encrypter);
- assert_eq!(got, padding);
-}
-
-#[test]
-fn problem_13 () {
- fn profile_for (email: &str) -> String {
- let mut params = HashMap::new();
- params.insert("email", email);
- params.insert("uid", "10");
- params.insert("role", "user");
- return matasano::create_query_string(params);
- }
-
- let key = util::random_aes_128_key();
- let encrypter = |email: &str| -> Vec<u8> {
- matasano::encrypt_aes_128_ecb(profile_for(email).as_bytes(), &key[..])
- };
- let decrypter = |ciphertext: &[u8]| -> Option<HashMap<String, String>> {
- let plaintext = matasano::decrypt_aes_128_ecb(ciphertext, &key[..]).unwrap();
- let plaintext_str = std::str::from_utf8(&plaintext[..]).unwrap();
- if let Some(params) = matasano::parse_query_string(plaintext_str) {
- return Some(
- params
- .into_iter()
- .map(|(k, v)| (k.to_owned(), v.to_owned()))
- .collect()
- );
- }
- else {
- return None;
- }
- };
-
- let (email, ciphertexts) = matasano::crack_querystring_aes_128_ecb(&encrypter);
- let mut expected = HashMap::new();
- expected.insert("email".to_owned(), email);
- expected.insert("uid".to_owned(), "10".to_owned());
- expected.insert("role".to_owned(), "admin".to_owned());
- assert!(ciphertexts.iter().any(|ciphertext| {
- decrypter(ciphertext).map(|params| params == expected).unwrap_or(false)
- }));
-}
-
-#[test]
-fn problem_14 () {
- let padding = b"Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWct\
- dG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpU\
- aGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\
- dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5v\
- LCBJIGp1c3QgZHJvdmUgYnkK".from_base64().unwrap();
- let front_padding: Vec<u8> = rand::thread_rng()
- .gen_iter()
- .take(rand::thread_rng().gen_range(1, 100))
- .collect();
- let fixed_padding = |input: &[u8]| -> Vec<u8> {
- return front_padding
- .iter()
- .chain(input.iter())
- .chain(padding.iter())
- .map(|x| *x)
- .collect()
- };
-
- let key = util::random_aes_128_key();
- let random_encrypter = |input: &[u8]| {
- let padded_input = fixed_padding(input);
- return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
- };
-
- let got = matasano::crack_padded_aes_128_ecb_with_prefix(&random_encrypter);
- assert_eq!(got, padding);
-}
-
-#[test]
-fn problem_15 () {
- assert_eq!(
- matasano::unpad_pkcs7(b"ICE ICE BABY\x04\x04\x04\x04"),
- Some(&b"ICE ICE BABY"[..])
- );
- assert_eq!(
- matasano::unpad_pkcs7(b"ICE ICE BABY\x05\x05\x05\x05"),
- None
- );
- assert_eq!(
- matasano::unpad_pkcs7(b"ICE ICE BABY\x01\x02\x03\x04"),
- None
- );
- assert_eq!(
- matasano::unpad_pkcs7(b"ICE ICE BABY\x00"),
- None
- );
- assert_eq!(
- matasano::unpad_pkcs7(b"\x04\x04\x04\x04"),
- Some(&b""[..])
- );
-}
-
-#[test]
-fn problem_16 () {
- let key = util::random_aes_128_key();
- let iv = util::random_aes_128_key();
- let prefix = "comment1=cooking%20MCs;userdata=";
- let suffix = ";comment2=%20like%20a%20pound%20of%20bacon";
- let admin = ";admin=true;";
-
- let escape = |input: &str| {
- input.replace("%", "%25").replace(";", "%3B").replace("=", "%3D")
- };
-
- let encode = |input: &str| -> Vec<u8> {
- let plaintext: Vec<u8> = prefix
- .as_bytes()
- .iter()
- .chain(escape(input).as_bytes().iter())
- .chain(suffix.as_bytes().iter())
- .map(|x| *x)
- .collect();
- return matasano::encrypt_aes_128_cbc(&plaintext[..], &key[..], &iv[..]);
- };
-
- let verify = |ciphertext: &[u8]| -> bool {
- let plaintext = matasano::decrypt_aes_128_cbc(ciphertext, &key[..], &iv[..]).unwrap();
- return (0..(plaintext.len() - admin.len())).any(|i| {
- plaintext
- .iter()
- .skip(i)
- .zip(admin.as_bytes().iter())
- .all(|(&c1, &c2)| c1 == c2)
- });
- };
-
- let ciphertext = matasano::crack_cbc_bitflipping(&encode);
- assert!(verify(&ciphertext[..]));
-}
-
-#[test]
-fn problem_17 () {
- let strings = [
- &b"MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc="[..],
- &b"MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic="[..],
- &b"MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw=="[..],
- &b"MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg=="[..],
- &b"MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl"[..],
- &b"MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA=="[..],
- &b"MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw=="[..],
- &b"MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8="[..],
- &b"MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g="[..],
- &b"MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93"[..],
- ];
- let key = util::random_aes_128_key();
-
- static mut chosen_plaintext_idx: usize = 0;
- let encrypter = || {
- let idx = rand::thread_rng().gen_range(0, strings.len());
- let plaintext = strings[idx].from_base64().unwrap();
- unsafe { chosen_plaintext_idx = idx };
- let iv = util::random_aes_128_key();
- return (
- iv,
- matasano::encrypt_aes_128_cbc(&plaintext[..], &key[..], &iv[..])
- );
- };
-
- let validator = |iv: &[u8], ciphertext: &[u8]| {
- let plaintext = matasano::decrypt_aes_128_cbc(
- ciphertext,
- &key[..],
- &iv[..]
- );
- return plaintext.is_some();
- };
-
- let (iv, ciphertext) = encrypter();
- for _ in 0..5 {
- let plaintext = matasano::crack_cbc_padding_oracle(
- &iv[..],
- &ciphertext[..],
- &validator
- );
- let idx = unsafe { chosen_plaintext_idx.clone() };
- let expected = strings[idx].from_base64().unwrap();
- assert_eq!(plaintext, expected);
- }
-}
-
-#[test]
-fn problem_18 () {
- let ciphertext = b"L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syL\
- XzhPweyyMTJULu/6/kXX0KSvoOLSFQ==".from_base64().unwrap();
- let plaintext = &b"Yo, VIP Let's kick it Ice, Ice, baby Ice, Ice, baby "[..];
- let got = matasano::aes_128_ctr(
- &ciphertext[..],
- b"YELLOW SUBMARINE",
- 0
- );
- assert_eq!(got, plaintext);
-}
-
-// #[test]
-// fn problem_19 () {
-// let key = util::random_aes_128_key();
-// let ciphertexts = util::read_as_base64_lines("data/19.txt")
-// .iter()
-// .map(|line| matasano::aes_128_ctr(&line[..], &key[..], 0))
-// .collect();
-// let plaintexts = matasano::crack_fixed_nonce_ctr_substitutions();
-// }
-
-#[test]
-fn problem_20 () {
- fn normalize (line_list: Vec<Vec<u8>>, len: usize) -> Vec<Vec<u8>> {
- line_list
- .iter()
- .map(|line| line.to_ascii_lowercase())
- .map(|line| line.iter().take(len).map(|x| *x).collect())
- .collect()
- }
-
- let key = util::random_aes_128_key();
- let ciphertexts = util::read_as_base64_lines("data/20.txt")
- .iter()
- .map(|line| matasano::aes_128_ctr(&line[..], &key[..], 0))
- .collect();
- let expected = util::read_as_lines("data/20.out.txt");
-
- let plaintexts = matasano::crack_fixed_nonce_ctr_statistically(
- ciphertexts
- );
-
- assert_eq!(
- normalize(plaintexts, 27),
- normalize(expected, 27)
- );
-}
-
-#[test]
-fn problem_21 () {
- let mut mt = matasano::MersenneTwister::from_seed(0x12345678);
- let got: Vec<u32> = mt.gen_iter().take(10).collect();
- let expected: Vec<u32> = vec![
- 0xC6979343, 0x0962D2FA, 0xA73A24A4, 0xE118A180, 0xB5475ABB,
- 0x64613C7C, 0x6F32F4DB, 0xF27BF199, 0x464DD8DC, 0x95C1FED6,
- ];
- assert_eq!(&got[..], &expected[..]);
-}
-
-#[test]
-fn problem_22 () {
- // std::thread::sleep_ms(rand::thread_rng().gen_range(40, 1000) * 1000);
- let seed = time::now().to_timespec().sec as u32;
- let mut mt = matasano::MersenneTwister::from_seed(seed);
- // std::thread::sleep_ms(rand::thread_rng().gen_range(40, 1000) * 1000);
- let output: u32 = mt.gen();
- let got = matasano::recover_mersenne_twister_seed_from_time(output).unwrap();
- assert_eq!(got, seed);
-}
-
-#[test]
-fn problem_23 () {
- let mut mt: matasano::MersenneTwister = rand::thread_rng().gen();
- let outputs: Vec<u32> = mt.gen_iter().take(624).collect();
- let mut mt2 = matasano::clone_mersenne_twister_from_output(&outputs[..]);
- for _ in 1..1000 {
- assert_eq!(mt.gen::<u32>(), mt2.gen::<u32>());
- }
-}
-
-#[test]
-fn problem_24 () {
- let key: u16 = rand::thread_rng().gen();
- let fixed_suffix = b"AAAAAAAAAAAAAA";
- let plaintext: Vec<u8> = rand::thread_rng()
- .gen_iter()
- .take(rand::thread_rng().gen_range(0, 32))
- .chain(fixed_suffix.iter().map(|x| *x))
- .collect();
- let ciphertext = matasano::mt19937_stream_cipher(&plaintext[..], key as u32);
- let got = matasano::recover_16_bit_mt19937_key(
- &ciphertext[..],
- &fixed_suffix[..],
- ).unwrap();
- assert_eq!(got, key);
-}
-
-#[test]
-fn problem_24_part_2 () {
- let seed = time::now().to_timespec().sec as u32;
- let mut mt = matasano::MersenneTwister::from_seed(seed);
- let token: Vec<u8> = mt.gen_iter().take(16).collect();
- let got = matasano::recover_mt19937_key_from_time(&token[..]).unwrap();
- assert_eq!(got, seed);
-}
diff --git a/tests/set1.rs b/tests/set1.rs
new file mode 100644
index 0000000..c9eece7
--- /dev/null
+++ b/tests/set1.rs
@@ -0,0 +1,90 @@
+extern crate matasano;
+extern crate rustc_serialize as serialize;
+
+use serialize::hex::FromHex;
+
+mod util;
+
+#[test]
+fn problem_1 () {
+ let hex = "49276d206b696c6c696e6720796f757220627261\
+ 696e206c696b65206120706f69736f6e6f757320\
+ 6d757368726f6f6d".from_hex().unwrap();
+ let base64 = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEg\
+ cG9pc29ub3VzIG11c2hyb29t";
+ let got = matasano::to_base64(&hex[..]);
+ assert_eq!(got, base64);
+}
+
+#[test]
+fn problem_2 () {
+ let bytes1 = "1c0111001f010100061a024b53535009181c".from_hex().unwrap();
+ let bytes2 = "686974207468652062756c6c277320657965".from_hex().unwrap();
+ let expected = "746865206b696420646f6e277420706c6179".from_hex().unwrap();
+ let got = matasano::fixed_xor(&bytes1[..], &bytes2[..]);
+ assert_eq!(got, expected);
+}
+
+#[test]
+fn problem_3 () {
+ let ciphertext = "1b37373331363f78151b7f2b783431333d783978\
+ 28372d363c78373e783a393b3736".from_hex().unwrap();
+ let plaintext = b"Cooking MC's like a pound of bacon";
+ let got = matasano::crack_single_byte_xor(&ciphertext[..]);
+ assert_eq!(got, &plaintext[..]);
+}
+
+#[test]
+fn problem_4 () {
+ let possibles = util::read_as_hex_lines("data/4.txt");
+ let plaintext = b"Now that the party is jumping\n";
+ let got = matasano::find_single_byte_xor_encrypted_string(&possibles[..]);
+ assert_eq!(got, plaintext);
+}
+
+#[test]
+fn problem_5 () {
+ let plaintext = b"Burning 'em, if you ain't quick and nimble\n\
+ I go crazy when I hear a cymbal";
+ let key = b"ICE";
+ let ciphertext = "0b3637272a2b2e63622c2e69692a23693a2a3c63\
+ 24202d623d63343c2a26226324272765272a282b\
+ 2f20430a652e2c652a3124333a653e2b2027630c\
+ 692b20283165286326302e27282f".from_hex().unwrap();
+ let got = matasano::repeating_key_xor(plaintext, key);
+ assert_eq!(got, ciphertext);
+}
+
+#[test]
+fn problem_6 () {
+ let ciphertext = util::read_as_base64("data/6.txt");
+ let plaintext = util::read("data/6.out.txt");
+ let key = matasano::crack_repeating_key_xor(&ciphertext[..]);
+ let got = matasano::repeating_key_xor(&ciphertext[..], &key[..]);
+ assert_eq!(got, plaintext);
+}
+
+#[test]
+fn problem_7 () {
+ let ciphertext = util::read_as_base64("data/7.txt");
+ let key = b"YELLOW SUBMARINE";
+ let plaintext = util::read("data/7.out.txt");
+ let got = matasano::decrypt_aes_128_ecb(&ciphertext[..], key);
+ assert_eq!(got, Some(plaintext));
+}
+
+#[test]
+fn problem_8 () {
+ let possibles = util::read_as_hex_lines("data/8.txt");
+ let ciphertext = "d880619740a8a19b7840a8a31c810a3d08649af7\
+ 0dc06f4fd5d2d69c744cd283e2dd052f6b641dbf\
+ 9d11b0348542bb5708649af70dc06f4fd5d2d69c\
+ 744cd2839475c9dfdbc1d46597949d9c7e82bf5a\
+ 08649af70dc06f4fd5d2d69c744cd28397a93eab\
+ 8d6aecd566489154789a6b0308649af70dc06f4f\
+ d5d2d69c744cd283d403180c98c8f6db1f2a3f9c\
+ 4040deb0ab51b29933f2c123c58386b06fba186a"
+ .from_hex().unwrap();
+ let got = matasano::find_aes_128_ecb_encrypted_string(&possibles[..]);
+ assert_eq!(got, ciphertext);
+}
diff --git a/tests/set2.rs b/tests/set2.rs
new file mode 100644
index 0000000..84f55b5
--- /dev/null
+++ b/tests/set2.rs
@@ -0,0 +1,230 @@
+extern crate matasano;
+extern crate rustc_serialize as serialize;
+extern crate rand;
+
+use std::borrow::ToOwned;
+use std::collections::HashMap;
+
+use rand::Rng;
+use serialize::base64::FromBase64;
+
+mod util;
+
+#[test]
+fn problem_9 () {
+ let block = b"YELLOW SUBMARINE";
+ let got = matasano::pad_pkcs7(block, 20);
+ assert_eq!(got, b"YELLOW SUBMARINE\x04\x04\x04\x04");
+}
+
+#[test]
+fn problem_10 () {
+ let ciphertext = util::read_as_base64("data/10.txt");
+ let key = b"YELLOW SUBMARINE";
+ let plaintext = util::read("data/10.out.txt");
+ let got = matasano::decrypt_aes_128_cbc(&ciphertext[..], key, &[0; 16]);
+ assert_eq!(got, Some(plaintext));
+}
+
+#[test]
+fn problem_11 () {
+ static mut last_mode: matasano::BlockCipherMode = matasano::BlockCipherMode::ECB;
+
+ fn random_padding (input: &[u8]) -> Vec<u8> {
+ let front_padding: Vec<u8> = rand::thread_rng()
+ .gen_iter()
+ .take(rand::thread_rng().gen_range(5, 10))
+ .collect();
+ let back_padding: Vec<u8> = rand::thread_rng()
+ .gen_iter()
+ .take(rand::thread_rng().gen_range(5, 10))
+ .collect();
+ return front_padding
+ .iter()
+ .chain(input.iter())
+ .chain(back_padding.iter())
+ .map(|x| *x)
+ .collect()
+ }
+
+ fn random_encrypter (input: &[u8]) -> Vec<u8> {
+ let key = util::random_aes_128_key();
+ let padded_input = random_padding(input);
+ if util::coinflip() {
+ unsafe {
+ last_mode = matasano::BlockCipherMode::ECB;
+ }
+ return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
+ }
+ else {
+ unsafe {
+ last_mode = matasano::BlockCipherMode::CBC;
+ }
+ let iv = util::random_aes_128_key();
+ return matasano::encrypt_aes_128_cbc(&padded_input[..], &key[..], &iv[..]);
+ }
+ }
+
+ for _ in 0..100 {
+ let got = matasano::detect_ecb_cbc(&random_encrypter, 16);
+ let expected = unsafe { &last_mode };
+ assert_eq!(&got, expected);
+ }
+}
+
+#[test]
+fn problem_12 () {
+ let padding = b"Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWct\
+ dG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpU\
+ aGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\
+ dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5v\
+ LCBJIGp1c3QgZHJvdmUgYnkK".from_base64().unwrap();
+ let fixed_padding = |input: &[u8]| -> Vec<u8> {
+ return input
+ .iter()
+ .chain(padding.iter())
+ .map(|x| *x)
+ .collect()
+ };
+
+ let key = util::random_aes_128_key();
+ let random_encrypter = |input: &[u8]| {
+ let padded_input = fixed_padding(input);
+ return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
+ };
+
+ let got = matasano::crack_padded_aes_128_ecb(&random_encrypter);
+ assert_eq!(got, padding);
+}
+
+#[test]
+fn problem_13 () {
+ fn profile_for (email: &str) -> String {
+ let mut params = HashMap::new();
+ params.insert("email", email);
+ params.insert("uid", "10");
+ params.insert("role", "user");
+ return matasano::create_query_string(params);
+ }
+
+ let key = util::random_aes_128_key();
+ let encrypter = |email: &str| -> Vec<u8> {
+ matasano::encrypt_aes_128_ecb(profile_for(email).as_bytes(), &key[..])
+ };
+ let decrypter = |ciphertext: &[u8]| -> Option<HashMap<String, String>> {
+ let plaintext = matasano::decrypt_aes_128_ecb(ciphertext, &key[..]).unwrap();
+ let plaintext_str = std::str::from_utf8(&plaintext[..]).unwrap();
+ if let Some(params) = matasano::parse_query_string(plaintext_str) {
+ return Some(
+ params
+ .into_iter()
+ .map(|(k, v)| (k.to_owned(), v.to_owned()))
+ .collect()
+ );
+ }
+ else {
+ return None;
+ }
+ };
+
+ let (email, ciphertexts) = matasano::crack_querystring_aes_128_ecb(&encrypter);
+ let mut expected = HashMap::new();
+ expected.insert("email".to_owned(), email);
+ expected.insert("uid".to_owned(), "10".to_owned());
+ expected.insert("role".to_owned(), "admin".to_owned());
+ assert!(ciphertexts.iter().any(|ciphertext| {
+ decrypter(ciphertext).map(|params| params == expected).unwrap_or(false)
+ }));
+}
+
+#[test]
+fn problem_14 () {
+ let padding = b"Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWct\
+ dG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpU\
+ aGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\
+ dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5v\
+ LCBJIGp1c3QgZHJvdmUgYnkK".from_base64().unwrap();
+ let front_padding: Vec<u8> = rand::thread_rng()
+ .gen_iter()
+ .take(rand::thread_rng().gen_range(1, 100))
+ .collect();
+ let fixed_padding = |input: &[u8]| -> Vec<u8> {
+ return front_padding
+ .iter()
+ .chain(input.iter())
+ .chain(padding.iter())
+ .map(|x| *x)
+ .collect()
+ };
+
+ let key = util::random_aes_128_key();
+ let random_encrypter = |input: &[u8]| {
+ let padded_input = fixed_padding(input);
+ return matasano::encrypt_aes_128_ecb(&padded_input[..], &key[..]);
+ };
+
+ let got = matasano::crack_padded_aes_128_ecb_with_prefix(&random_encrypter);
+ assert_eq!(got, padding);
+}
+
+#[test]
+fn problem_15 () {
+ assert_eq!(
+ matasano::unpad_pkcs7(b"ICE ICE BABY\x04\x04\x04\x04"),
+ Some(&b"ICE ICE BABY"[..])
+ );
+ assert_eq!(
+ matasano::unpad_pkcs7(b"ICE ICE BABY\x05\x05\x05\x05"),
+ None
+ );
+ assert_eq!(
+ matasano::unpad_pkcs7(b"ICE ICE BABY\x01\x02\x03\x04"),
+ None
+ );
+ assert_eq!(
+ matasano::unpad_pkcs7(b"ICE ICE BABY\x00"),
+ None
+ );
+ assert_eq!(
+ matasano::unpad_pkcs7(b"\x04\x04\x04\x04"),
+ Some(&b""[..])
+ );
+}
+
+#[test]
+fn problem_16 () {
+ let key = util::random_aes_128_key();
+ let iv = util::random_aes_128_key();
+ let prefix = "comment1=cooking%20MCs;userdata=";
+ let suffix = ";comment2=%20like%20a%20pound%20of%20bacon";
+ let admin = ";admin=true;";
+
+ let escape = |input: &str| {
+ input.replace("%", "%25").replace(";", "%3B").replace("=", "%3D")
+ };
+
+ let encode = |input: &str| -> Vec<u8> {
+ let plaintext: Vec<u8> = prefix
+ .as_bytes()
+ .iter()
+ .chain(escape(input).as_bytes().iter())
+ .chain(suffix.as_bytes().iter())
+ .map(|x| *x)
+ .collect();
+ return matasano::encrypt_aes_128_cbc(&plaintext[..], &key[..], &iv[..]);
+ };
+
+ let verify = |ciphertext: &[u8]| -> bool {
+ let plaintext = matasano::decrypt_aes_128_cbc(ciphertext, &key[..], &iv[..]).unwrap();
+ return (0..(plaintext.len() - admin.len())).any(|i| {
+ plaintext
+ .iter()
+ .skip(i)
+ .zip(admin.as_bytes().iter())
+ .all(|(&c1, &c2)| c1 == c2)
+ });
+ };
+
+ let ciphertext = matasano::crack_cbc_bitflipping(&encode);
+ assert!(verify(&ciphertext[..]));
+}
diff --git a/tests/set3.rs b/tests/set3.rs
new file mode 100644
index 0000000..a6c32bc
--- /dev/null
+++ b/tests/set3.rs
@@ -0,0 +1,169 @@
+extern crate matasano;
+extern crate rustc_serialize as serialize;
+extern crate rand;
+extern crate time;
+
+use std::ascii::AsciiExt;
+
+use rand::{Rng, SeedableRng};
+use serialize::base64::FromBase64;
+
+mod util;
+
+#[test]
+fn problem_17 () {
+ let strings = [
+ &b"MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc="[..],
+ &b"MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic="[..],
+ &b"MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw=="[..],
+ &b"MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg=="[..],
+ &b"MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl"[..],
+ &b"MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA=="[..],
+ &b"MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw=="[..],
+ &b"MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8="[..],
+ &b"MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g="[..],
+ &b"MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93"[..],
+ ];
+ let key = util::random_aes_128_key();
+
+ static mut chosen_plaintext_idx: usize = 0;
+ let encrypter = || {
+ let idx = rand::thread_rng().gen_range(0, strings.len());
+ let plaintext = strings[idx].from_base64().unwrap();
+ unsafe { chosen_plaintext_idx = idx };
+ let iv = util::random_aes_128_key();
+ return (
+ iv,
+ matasano::encrypt_aes_128_cbc(&plaintext[..], &key[..], &iv[..])
+ );
+ };
+
+ let validator = |iv: &[u8], ciphertext: &[u8]| {
+ let plaintext = matasano::decrypt_aes_128_cbc(
+ ciphertext,
+ &key[..],
+ &iv[..]
+ );
+ return plaintext.is_some();
+ };
+
+ let (iv, ciphertext) = encrypter();
+ for _ in 0..5 {
+ let plaintext = matasano::crack_cbc_padding_oracle(
+ &iv[..],
+ &ciphertext[..],
+ &validator
+ );
+ let idx = unsafe { chosen_plaintext_idx.clone() };
+ let expected = strings[idx].from_base64().unwrap();
+ assert_eq!(plaintext, expected);
+ }
+}
+
+#[test]
+fn problem_18 () {
+ let ciphertext = b"L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syL\
+ XzhPweyyMTJULu/6/kXX0KSvoOLSFQ==".from_base64().unwrap();
+ let plaintext = &b"Yo, VIP Let's kick it Ice, Ice, baby Ice, Ice, baby "[..];
+ let got = matasano::aes_128_ctr(
+ &ciphertext[..],
+ b"YELLOW SUBMARINE",
+ 0
+ );
+ assert_eq!(got, plaintext);
+}
+
+// #[test]
+// fn problem_19 () {
+// let key = util::random_aes_128_key();
+// let ciphertexts = util::read_as_base64_lines("data/19.txt")
+// .iter()
+// .map(|line| matasano::aes_128_ctr(&line[..], &key[..], 0))
+// .collect();
+// let plaintexts = matasano::crack_fixed_nonce_ctr_substitutions();
+// }
+
+#[test]
+fn problem_20 () {
+ fn normalize (line_list: Vec<Vec<u8>>, len: usize) -> Vec<Vec<u8>> {
+ line_list
+ .iter()
+ .map(|line| line.to_ascii_lowercase())
+ .map(|line| line.iter().take(len).map(|x| *x).collect())
+ .collect()
+ }
+
+ let key = util::random_aes_128_key();
+ let ciphertexts = util::read_as_base64_lines("data/20.txt")
+ .iter()
+ .map(|line| matasano::aes_128_ctr(&line[..], &key[..], 0))
+ .collect();
+ let expected = util::read_as_lines("data/20.out.txt");
+
+ let plaintexts = matasano::crack_fixed_nonce_ctr_statistically(
+ ciphertexts
+ );
+
+ assert_eq!(
+ normalize(plaintexts, 27),
+ normalize(expected, 27)
+ );
+}
+
+#[test]
+fn problem_21 () {
+ let mut mt = matasano::MersenneTwister::from_seed(0x12345678);
+ let got: Vec<u32> = mt.gen_iter().take(10).collect();
+ let expected: Vec<u32> = vec![
+ 0xC6979343, 0x0962D2FA, 0xA73A24A4, 0xE118A180, 0xB5475ABB,
+ 0x64613C7C, 0x6F32F4DB, 0xF27BF199, 0x464DD8DC, 0x95C1FED6,
+ ];
+ assert_eq!(&got[..], &expected[..]);
+}
+
+#[test]
+fn problem_22 () {
+ // std::thread::sleep_ms(rand::thread_rng().gen_range(40, 1000) * 1000);
+ let seed = time::now().to_timespec().sec as u32;
+ let mut mt = matasano::MersenneTwister::from_seed(seed);
+ // std::thread::sleep_ms(rand::thread_rng().gen_range(40, 1000) * 1000);
+ let output: u32 = mt.gen();
+ let got = matasano::recover_mersenne_twister_seed_from_time(output).unwrap();
+ assert_eq!(got, seed);
+}
+
+#[test]
+fn problem_23 () {
+ let mut mt: matasano::MersenneTwister = rand::thread_rng().gen();
+ let outputs: Vec<u32> = mt.gen_iter().take(624).collect();
+ let mut mt2 = matasano::clone_mersenne_twister_from_output(&outputs[..]);
+ for _ in 1..1000 {
+ assert_eq!(mt.gen::<u32>(), mt2.gen::<u32>());
+ }
+}
+
+#[test]
+fn problem_24 () {
+ let key: u16 = rand::thread_rng().gen();
+ let fixed_suffix = b"AAAAAAAAAAAAAA";
+ let plaintext: Vec<u8> = rand::thread_rng()
+ .gen_iter()
+ .take(rand::thread_rng().gen_range(0, 32))
+ .chain(fixed_suffix.iter().map(|x| *x))
+ .collect();
+ let ciphertext = matasano::mt19937_stream_cipher(&plaintext[..], key as u32);
+ let got = matasano::recover_16_bit_mt19937_key(
+ &ciphertext[..],
+ &fixed_suffix[..],
+ ).unwrap();
+ assert_eq!(got, key);
+}
+
+#[test]
+fn problem_24_part_2 () {
+ let seed = time::now().to_timespec().sec as u32;
+ let mut mt = matasano::MersenneTwister::from_seed(seed);
+ let token: Vec<u8> = mt.gen_iter().take(16).collect();
+ let got = matasano::recover_mt19937_key_from_time(&token[..]).unwrap();
+ assert_eq!(got, seed);
+}
diff --git a/tests/util.rs b/tests/util.rs
index 79076fe..bb41fb6 100644
--- a/tests/util.rs
+++ b/tests/util.rs
@@ -1,9 +1,14 @@
+#![allow(dead_code)]
+
+extern crate rand;
+extern crate rustc_serialize as serialize;
+
use std::io::prelude::*;
use std::fs::File;
-use rand::Rng;
-use serialize::base64::FromBase64;
-use serialize::hex::FromHex;
+use self::rand::Rng;
+use self::serialize::base64::FromBase64;
+use self::serialize::hex::FromHex;
pub fn read_as_hex_lines (filename: &str) -> Vec<Vec<u8>> {
let fh = File::open(filename).unwrap();
@@ -45,10 +50,10 @@ pub fn read (filename: &str) -> Vec<u8> {
pub fn random_aes_128_key () -> [u8; 16] {
let mut key = [0; 16];
- ::rand::thread_rng().fill_bytes(&mut key);
+ self::rand::thread_rng().fill_bytes(&mut key);
return key;
}
pub fn coinflip () -> bool {
- ::rand::thread_rng().gen()
+ self::rand::thread_rng().gen()
}