From f9ddf4cccd23774123c2c2ba324168d79c2c3f08 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Thu, 16 Jun 2022 07:47:13 -0400 Subject: [PATCH] Challenge 12 decrypt first block. --- src/bytes.rs | 4 +++ src/set2.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index 5dc0b98..faa78bf 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -16,6 +16,10 @@ impl Bytes { String::from(std::str::from_utf8(&v).unwrap()) } + pub fn first_block(&self, length: usize) -> Bytes { + Bytes(self.0[0..length].to_vec()) + } + pub fn random(length: usize) -> Bytes { Bytes( (0..length) diff --git a/src/set2.rs b/src/set2.rs index dd11ed3..d137999 100644 --- a/src/set2.rs +++ b/src/set2.rs @@ -117,18 +117,72 @@ pub fn challenge12() { cipher } - let key = Bytes::random(16); // consistent but unknown key - - // 1. Find key length - let mut v = vec![]; - let initial_cipher_len = encryption_oracle(&key, &Bytes(v.to_vec())).0.len(); - let mut new_cipher_len = initial_cipher_len; - while initial_cipher_len == new_cipher_len { - v.push(b'A'); - let cipher = encryption_oracle(&key, &Bytes(v.to_vec())); - new_cipher_len = cipher.0.len(); + fn get_length(key: &Bytes) -> usize { + // Detect cipher length + let mut v = vec![]; + let initial_cipher_len = encryption_oracle(&key, &Bytes(v.to_vec())).0.len(); + let mut new_cipher_len = initial_cipher_len; + while initial_cipher_len == new_cipher_len { + v.push(b'A'); + let cipher = encryption_oracle(&key, &Bytes(v.to_vec())); + new_cipher_len = cipher.0.len(); + } + let key_length = new_cipher_len - initial_cipher_len; + key_length } - let key_length = new_cipher_len - initial_cipher_len; - println!("[xxxx] Challenge 12: key_length={}", key_length); + fn is_encryption_ecb(key: &Bytes) -> bool { + let data = Bytes::from_utf8("aaaabbbbccccddddaaaabbbbccccdddd"); + let cipher = encryption_oracle(&key, &data); + if cipher.has_duplicated_cycle(16) { + true + } else { + false + } + } + + fn decode_first_block(key: &Bytes) -> Bytes { + let block_size = 16; + let mut decoded_first_block = vec![]; + + for i in (0..16).rev() { + let mut padding_text = vec![b'A'; i]; + let expected = encryption_oracle(&key, &Bytes(padding_text.to_vec())); + let expected_first_block = expected.first_block(block_size); + padding_text.append(&mut decoded_first_block.to_vec()); + for i in 0..255 { + let mut text = padding_text.to_vec(); + text.push(i); + let text = Bytes(text.to_vec()); + let cipher_first_block = encryption_oracle(&key, &text).first_block(block_size); + if cipher_first_block.0 == expected_first_block.0 { + decoded_first_block.push(i); + break; + } + } + } + Bytes(decoded_first_block) + } + + let key = Bytes::random(16); // consistent but unknown key + let key_length = get_length(&key); // 1. discover block size + assert_eq!(is_encryption_ecb(&key), true); // 2. confirm oracle uses ecb + let first_block = decode_first_block(&key); // 3.-6. + + println!( + "[xxxx] Challenge 12: key_length={}, first_block={}", + key_length, + first_block.to_utf8() + ); + + // Just some experiments to see how openssl does padding + // println!( + // "len={}", + // ecb::encrypt( + // &Bytes::from_utf8("aaaabbbbccccdddd"), + // &Bytes::from_utf8("aaaabbbbccccddddaaaabbbbccccdddd") + // ) + // .0 + // .len() + // ); }