Compare commits

...

2 Commits

Author SHA1 Message Date
Valentin Ochs f806cfec45 Formatting. q14. q15. 2019-09-04 19:22:26 +02:00
Valentin Ochs 62c92eecbb q13 2019-09-03 21:28:56 +02:00
2 changed files with 197 additions and 17 deletions

View File

@ -58,7 +58,7 @@ impl Aes {
Some(data.clone())
}
pub fn ecb(&self, mut data: Vec<u8>, mode: Mode) -> Option<Vec<u8>> {
pub fn ecb(&self, data: Vec<u8>, mode: Mode) -> Option<Vec<u8>> {
if (!self.pad) && (data.len() % Self::BLOCK_SIZE != 0) {
return None;
}

View File

@ -168,8 +168,8 @@ fn q11() {
let key: Vec<u8> = rng.sample_iter(&dist).take(16).collect();
let iv: Vec<u8> = rng.sample_iter(&dist).take(16).collect();
let aes = crypto::Aes::new(&key, true).unwrap();
let mut start: Vec<u8> = rng.sample_iter(&dist).take(rng.gen_range(5,11)).collect();
let mut end: Vec<u8> = rng.sample_iter(&dist).take(rng.gen_range(5,11)).collect();
let mut start: Vec<u8> = rng.sample_iter(&dist).take(rng.gen_range(5, 11)).collect();
let mut end: Vec<u8> = rng.sample_iter(&dist).take(rng.gen_range(5, 11)).collect();
start.append(&mut data);
start.append(&mut end);
@ -180,21 +180,21 @@ fn q11() {
}
};
let oracle = |data: &Vec<u8>| -> bool {
data[16..32] == data[32..48]
};
let oracle = |data: &Vec<u8>| -> bool { data[16..32] == data[32..48] };
for i in 0..128 {
let data = [0u8;64];
let data = [0u8; 64];
let (ecb, data) = black_box(data.to_vec());
assert!(ecb == oracle(&data));
}
}
fn q12()
{
fn q12() {
println!("Running q12");
let key: Vec<u8> = rand::thread_rng().sample_iter(rand::distributions::Standard).take(16).collect();
let key: Vec<u8> = rand::thread_rng()
.sample_iter(rand::distributions::Standard)
.take(16)
.collect();
let plaintext: Vec<u8> = Bytes::from_base64("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK").into();
let aes = crate::crypto::Aes::new(&key, true).unwrap();
@ -204,7 +204,10 @@ fn q12()
};
let starting_size = blackbox(Vec::new()).len();
let (first_increment, next_size) = (0..).map(|x:usize| (x, blackbox(std::iter::repeat(0u8).take(x).collect()).len())).find(|(i,x)| *x != starting_size).unwrap();
let (first_increment, next_size) = (0..)
.map(|x: usize| (x, blackbox(std::iter::repeat(0u8).take(x).collect()).len()))
.find(|(_, x)| *x != starting_size)
.unwrap();
let block_size = next_size - starting_size;
println!(" Block size is {}", block_size);
assert!(block_size == 16);
@ -220,15 +223,23 @@ fn q12()
let mut known: Vec<u8> = Vec::with_capacity(data_length);
println!(" Data length: {}", data_length);
for byte_index in 0..data_length
{
let nulls: Vec<u8> = std::iter::repeat(0u8).take(starting_size - known.len() - 1).collect();
for _ in 0..data_length {
let nulls: Vec<u8> = std::iter::repeat(0u8)
.take(starting_size - known.len() - 1)
.collect();
let target_block = &blackbox(nulls.clone())[0..starting_size];
let mut found = false;
'byteiter: for b in 0u8..=255u8 {
let this_block = &blackbox(nulls.iter().chain(known.iter()).chain(std::iter::once(&b)).cloned().take(starting_size).collect())[0..starting_size];
if this_block == target_block
{
let this_block = &blackbox(
nulls
.iter()
.chain(known.iter())
.chain(std::iter::once(&b))
.cloned()
.take(starting_size)
.collect(),
)[0..starting_size];
if this_block == target_block {
known.push(b);
found = true;
break 'byteiter;
@ -239,6 +250,172 @@ fn q12()
// println!(" {}", String::from_utf8(known).unwrap().replace("\n", "\n "));
}
fn q13() {
println!("Running q13");
let key: Vec<u8> = rand::thread_rng()
.sample_iter(rand::distributions::Standard)
.take(16)
.collect();
let parse = |x: &str| -> std::collections::HashMap<String, String> {
let mut out = std::collections::HashMap::new();
for pair in x.split(|y| y == '&') {
let elements: Vec<&str> = pair.split(|z| z == '=').collect();
if elements.len() == 2 {
out.insert(elements[0].to_owned(), elements[1].to_owned());
}
}
out
};
let profile_for = |mail: &str| -> String {
format!(
"email={}&uid=10&role=user",
mail.replace("&", "").replace("=", "")
)
};
let encrypt = |profile: &str| -> Vec<u8> {
let profile: Vec<u8> = profile.bytes().collect();
let aes = crypto::Aes::new(&key, true).unwrap();
aes.ecb(profile, Mode::Encrypt).unwrap()
};
let is_admin = |profile: Vec<u8>| -> bool {
let aes = crypto::Aes::new(&key, true).unwrap();
let profile = aes.ecb(profile, Mode::Decrypt).unwrap();
let profile = String::from_utf8(profile).unwrap();
parse(&profile)["role"] == "admin"
};
let mail1 = "a".repeat(32 - "email=".len() - "@example.com&uid=10&role=".len());
let mail1 = mail1 + "@example.com";
let part1: &[u8] = &encrypt(&profile_for(&mail1))[0..32];
let mail2 = " ".repeat(16 - "email=".len());
let mail2 = mail2 + "admin";
let padding_char = (16 - "admin".len()) as u8;
let mail2 = mail2
+ &String::from_utf8(vec![padding_char])
.unwrap()
.repeat(padding_char as usize);
let part2: &[u8] = &encrypt(&profile_for(&mail2))[16..32];
let whole: Vec<u8> = part1.iter().chain(part2.iter()).cloned().collect();
assert!(is_admin(whole));
}
fn q14() {
println!("Running q14");
let key: Vec<u8> = rand::thread_rng()
.sample_iter(rand::distributions::Standard)
.take(16)
.collect();
let plaintext: Vec<u8> = Bytes::from_base64("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK").into();
let aes = crate::crypto::Aes::new(&key, true).unwrap();
let prefix: Vec<u8> = rand::thread_rng()
.sample_iter(rand::distributions::Standard)
.take(rand::thread_rng().gen_range(5, 11))
.collect();
let blackbox = |mut attacker_data: Vec<u8>| -> Vec<u8> {
let mut data: Vec<u8> = prefix.clone();
data.append(&mut attacker_data);
data.append(&mut plaintext.clone());
let rv = aes.ecb(data, Mode::Encrypt).unwrap();
rv
};
let starting_size = blackbox(Vec::new()).len();
let (first_increment, next_size) = (0..)
.map(|x: usize| (x, blackbox(std::iter::repeat(0u8).take(x).collect()).len()))
.find(|(_, x)| *x != starting_size)
.unwrap();
println!(" First size increment at {}", first_increment);
let block_size = next_size - starting_size;
println!(" Block size is {}", block_size);
assert!(block_size == 16);
let long_block = blackbox(std::iter::repeat(0u8).take(1280).collect());
let using_ecb = long_block[480..496] == long_block[496..512];
println!(" Using ECB: {}", using_ecb);
assert!(using_ecb);
let all_zero_ciphertext = blackbox(std::iter::repeat(0u8).take(block_size).collect());
let first_different_block = |x: usize| -> usize {
let data: Vec<u8> = std::iter::repeat(0u8)
.take(x)
.chain(std::iter::once(1u8))
.chain(std::iter::repeat(0u8).take(block_size - 1 - x))
.collect();
let data: Vec<u8> = blackbox(data);
data.chunks_exact(block_size)
.zip(all_zero_ciphertext.chunks_exact(block_size))
.enumerate()
.find(|(_, (a, b))| a != b)
.unwrap()
.0
};
let start_block = first_different_block(0);
let mut prefix_size = start_block * block_size + block_size - 1;
for i in 2..block_size {
let diff_block = first_different_block(i);
if diff_block == start_block {
prefix_size = start_block * block_size + block_size - 1 - i;
}
}
println!(" Prefix length is {}", prefix_size);
assert!(prefix_size == prefix.len());
let data_length = starting_size - first_increment - prefix_size;
let mut known: Vec<u8> = Vec::with_capacity(data_length);
println!(" Data length: {}", data_length);
assert!(data_length == plaintext.len());
let prefix_total = (prefix_size + block_size - 1) / block_size * block_size;
let prefix_nulls = prefix_total - prefix_size;
let starting_size = (prefix_total + data_length + block_size - 1) / block_size * block_size;
for _ in 0..data_length {
let nulls: Vec<u8> = std::iter::repeat(0u8)
.take(starting_size - prefix_size - known.len() - 1)
.collect();
let target_block = &blackbox(nulls.clone())[prefix_total..starting_size];
let mut found = false;
'byteiter: for b in 0u8..=255u8 {
let this_block = &blackbox(
nulls
.iter()
.chain(known.iter())
.chain(std::iter::once(&b))
.cloned()
.take(starting_size)
.collect(),
)[prefix_total..starting_size];
if this_block == target_block {
known.push(b);
found = true;
break 'byteiter;
}
}
assert!(found);
}
assert!(known == plaintext);
}
fn q15() {
println!("Running q15");
let input = b"ICE ICE BABY\x05\x05\x05\x05";
let output = Bytes::from(&input[..]);
let output = output.unpad();
assert!(output == None);
let input = b"ICE ICE BABY\x04\x04\x04\x04";
let output = Bytes::from(&input[..]);
let output = output.unpad().unwrap();
assert!(output.to_string().unwrap() == "ICE ICE BABY");
}
fn main() {
q01();
q02();
@ -252,4 +429,7 @@ fn main() {
q10();
q11();
q12();
q13();
q14();
q15();
}