summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2015-04-07 01:18:04 -0400
committerJesse Luehrs <doy@tozt.net>2015-04-07 01:18:04 -0400
commita16eee14a18d4c345d6485593d3543e342c86af3 (patch)
treee0b0215eb1b7ea2de66803ec9ea5b70e69878db4
parent4213d57bdf70b6339bc4affdc751c296f9aa14f0 (diff)
downloadmatasano-a16eee14a18d4c345d6485593d3543e342c86af3.tar.gz
matasano-a16eee14a18d4c345d6485593d3543e342c86af3.zip
problem 26
-rw-r--r--src/crack.rs12
-rw-r--r--src/lib.rs1
-rw-r--r--tests/set4.rs38
3 files changed, 51 insertions, 0 deletions
diff --git a/src/crack.rs b/src/crack.rs
index abfd84a..b5ff9ff 100644
--- a/src/crack.rs
+++ b/src/crack.rs
@@ -435,6 +435,18 @@ pub fn crack_aes_128_ctr_random_access<F> (ciphertext: &[u8], edit: F) -> Vec<u8
return fixed_xor(&keystream[..], ciphertext);
}
+pub fn crack_ctr_bitflipping<F> (f: &F) -> Vec<u8> where F: Fn(&str) -> Vec<u8> {
+ let ciphertext = f("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
+ let replacement = fixed_xor(&ciphertext[32..44], b";admin=true;");
+ return ciphertext[..32]
+ .iter()
+ .chain(replacement.iter())
+ .chain(ciphertext[44..].iter())
+ .map(|x| *x)
+ .collect();
+}
+
+
fn crack_single_byte_xor_with_confidence (input: &[u8]) -> (u8, f64) {
let mut min_diff = 100.0;
let mut best_key = 0;
diff --git a/src/lib.rs b/src/lib.rs
index 6cfb2d3..4209c0d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -43,3 +43,4 @@ pub use crack::clone_mersenne_twister_from_output;
pub use crack::recover_16_bit_mt19937_key;
pub use crack::recover_mt19937_key_from_time;
pub use crack::crack_aes_128_ctr_random_access;
+pub use crack::crack_ctr_bitflipping;
diff --git a/tests/set4.rs b/tests/set4.rs
index 3967f85..35c3edf 100644
--- a/tests/set4.rs
+++ b/tests/set4.rs
@@ -48,3 +48,41 @@ fn problem_25 () {
let got = matasano::crack_aes_128_ctr_random_access(&ciphertext[..], edit);
assert_eq!(&got[..], &plaintext[..]);
}
+
+#[test]
+fn problem_26 () {
+ let key = util::random_aes_128_key();
+ let nonce = rand::thread_rng().gen();
+ 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::aes_128_ctr(&plaintext[..], &key[..], nonce);
+ };
+
+ let verify = |ciphertext: &[u8]| -> bool {
+ let plaintext = matasano::aes_128_ctr(ciphertext, &key[..], nonce);
+ 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_ctr_bitflipping(&encode);
+ assert!(verify(&ciphertext[..]));
+}