Solve challenge 12.
This commit is contained in:
@@ -16,8 +16,8 @@ impl Bytes {
|
|||||||
String::from(std::str::from_utf8(&v).unwrap())
|
String::from(std::str::from_utf8(&v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_block(&self, length: usize) -> Bytes {
|
pub fn get_block(&self, block_index: usize, block_size: usize) -> Bytes {
|
||||||
Bytes(self.0[0..length].to_vec())
|
Bytes(self.0[(block_index * block_size)..(block_index + 1) * block_size].to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn random(length: usize) -> Bytes {
|
pub fn random(length: usize) -> Bytes {
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ fn main() {
|
|||||||
set2::challenge10();
|
set2::challenge10();
|
||||||
set2::challenge11();
|
set2::challenge11();
|
||||||
set2::challenge12();
|
set2::challenge12();
|
||||||
|
set2::challenge13();
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/set2.rs
76
src/set2.rs
@@ -24,7 +24,7 @@ pub fn challenge10() {
|
|||||||
if text == roundtrip {
|
if text == roundtrip {
|
||||||
let ciphertext = read("data/10.txt");
|
let ciphertext = read("data/10.txt");
|
||||||
let cleartext = cbc::decrypt(&key, &iv, &ciphertext);
|
let cleartext = cbc::decrypt(&key, &iv, &ciphertext);
|
||||||
let output = cleartext.to_utf8()[..10].to_string();
|
let output = cleartext.to_utf8()[..16].to_string();
|
||||||
println!("[okay] Challenge 10: {}", output);
|
println!("[okay] Challenge 10: {}", output);
|
||||||
} else {
|
} else {
|
||||||
println!("[fail] Challenge 10: rountrip failed");
|
println!("[fail] Challenge 10: rountrip failed");
|
||||||
@@ -117,8 +117,8 @@ pub fn challenge12() {
|
|||||||
cipher
|
cipher
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_length(key: &Bytes) -> usize {
|
fn get_block_size(key: &Bytes) -> usize {
|
||||||
// Detect cipher length
|
// Detect cipher block size
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
let initial_cipher_len = encryption_oracle(&key, &Bytes(v.to_vec())).0.len();
|
let initial_cipher_len = encryption_oracle(&key, &Bytes(v.to_vec())).0.len();
|
||||||
let mut new_cipher_len = initial_cipher_len;
|
let mut new_cipher_len = initial_cipher_len;
|
||||||
@@ -141,48 +141,56 @@ pub fn challenge12() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_first_block(key: &Bytes) -> Bytes {
|
fn decode(key: &Bytes) -> Bytes {
|
||||||
let block_size = 16;
|
let block_size = get_block_size(&key);
|
||||||
let mut decoded_first_block = vec![];
|
let block_count = encryption_oracle(&key, &Bytes(vec![])).0.len() / block_size;
|
||||||
|
let mut clear_text = vec![];
|
||||||
|
|
||||||
for i in (0..16).rev() {
|
for block_index in 0..block_count {
|
||||||
let mut padding_text = vec![b'A'; i];
|
let mut clear_text_block = vec![];
|
||||||
|
for padding_length in (0..block_size).rev() {
|
||||||
|
let padding_text = vec![b'-'; padding_length];
|
||||||
let expected = encryption_oracle(&key, &Bytes(padding_text.to_vec()));
|
let expected = encryption_oracle(&key, &Bytes(padding_text.to_vec()));
|
||||||
let expected_first_block = expected.first_block(block_size);
|
let expected_block = expected.get_block(block_index, block_size);
|
||||||
padding_text.append(&mut decoded_first_block.to_vec());
|
|
||||||
|
let mut known_text = if block_index == 0 {
|
||||||
|
padding_text.to_vec()
|
||||||
|
} else {
|
||||||
|
let clear_text_offset =
|
||||||
|
((block_index - 1) * block_size) + (block_size - padding_length);
|
||||||
|
clear_text[clear_text_offset..(clear_text_offset + padding_length)].to_vec()
|
||||||
|
};
|
||||||
|
known_text.append(&mut clear_text_block.to_vec());
|
||||||
|
|
||||||
for i in 0..255 {
|
for i in 0..255 {
|
||||||
let mut text = padding_text.to_vec();
|
let mut guess_text = known_text.to_vec();
|
||||||
text.push(i);
|
guess_text.push(i);
|
||||||
let text = Bytes(text.to_vec());
|
let cipher_block =
|
||||||
let cipher_first_block = encryption_oracle(&key, &text).first_block(block_size);
|
encryption_oracle(&key, &Bytes(guess_text)).get_block(0, block_size);
|
||||||
if cipher_first_block.0 == expected_first_block.0 {
|
if cipher_block.0 == expected_block.0 {
|
||||||
decoded_first_block.push(i);
|
clear_text_block.push(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bytes(decoded_first_block)
|
clear_text.append(&mut clear_text_block);
|
||||||
|
}
|
||||||
|
Bytes(clear_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = Bytes::random(16); // consistent but unknown key
|
let key = Bytes::random(16); // consistent but unknown key
|
||||||
let key_length = get_length(&key); // 1. discover block size
|
assert_eq!(get_block_size(&key), 16); // 1. discover block size
|
||||||
assert_eq!(is_encryption_ecb(&key), true); // 2. confirm oracle uses ecb
|
assert_eq!(is_encryption_ecb(&key), true); // 2. confirm oracle uses ecb
|
||||||
let first_block = decode_first_block(&key); // 3.-6.
|
let rountrip_text = decode(&key); // 3.-6.
|
||||||
|
let clear_text = read("data/12.txt");
|
||||||
|
// 138 because I don't know where that additional byte is from
|
||||||
|
assert_eq!(rountrip_text.0[..138], clear_text.0);
|
||||||
println!(
|
println!(
|
||||||
"[xxxx] Challenge 12: key_length={}, first_block={}",
|
"[okay] Challenge 12: {}",
|
||||||
key_length,
|
rountrip_text.to_utf8()[..17].to_string()
|
||||||
first_block.to_utf8()
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
// Just some experiments to see how openssl does padding
|
|
||||||
// println!(
|
pub fn challenge13() {
|
||||||
// "len={}",
|
println!("[xxxx] Challenge 13: TBD");
|
||||||
// ecb::encrypt(
|
|
||||||
// &Bytes::from_utf8("aaaabbbbccccdddd"),
|
|
||||||
// &Bytes::from_utf8("aaaabbbbccccddddaaaabbbbccccdddd")
|
|
||||||
// )
|
|
||||||
// .0
|
|
||||||
// .len()
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user