summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/aes.rs8
-rw-r--r--src/lib.rs1
-rw-r--r--tests/lib.rs38
3 files changed, 47 insertions, 0 deletions
diff --git a/src/aes.rs b/src/aes.rs
index 5ef1d8b..40d1c41 100644
--- a/src/aes.rs
+++ b/src/aes.rs
@@ -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;
diff --git a/src/lib.rs b/src/lib.rs
index f8b7da7..198ce83 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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[..]));
+}