diff options
-rw-r--r-- | src/aes.rs | 8 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | tests/lib.rs | 38 |
3 files changed, 47 insertions, 0 deletions
@@ -245,6 +245,14 @@ pub fn crack_querystring_aes_128_ecb<F> (encrypter: &F) -> (String, Vec<Vec<u8>> return calculate_possible_admin_ciphertexts(admin_block); } +pub fn crack_cbc_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> { + let mut ciphertext = f("AAAAAAAAAAAAAAAA:admin<true:AAAA"); + ciphertext[32] = ciphertext[32] ^ 0x01; + ciphertext[38] = ciphertext[38] ^ 0x01; + ciphertext[43] = ciphertext[43] ^ 0x01; + return ciphertext; +} + fn count_duplicate_blocks (input: &[u8], block_size: usize) -> usize { let mut set = HashSet::new(); let mut dups = 0; @@ -18,6 +18,7 @@ pub use aes::detect_ecb_cbc; pub use aes::crack_padded_aes_128_ecb; pub use aes::crack_padded_aes_128_ecb_with_prefix; pub use aes::crack_querystring_aes_128_ecb; +pub use aes::crack_cbc_bitflipping; pub use base64::to_base64; pub use http::parse_query_string; pub use http::create_query_string; diff --git a/tests/lib.rs b/tests/lib.rs index 72c808a..cc37ec4 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -302,3 +302,41 @@ fn problem_15 () { Some(&b""[..]) ); } + +#[test] +fn problem_16 () { + let key = random_aes_128_key(); + let iv = 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[..]); + 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[..])); +} |