Implement challenge 27

This commit is contained in:
2022-08-16 19:16:48 -04:00
parent caf6d35b59
commit 54047b3450
2 changed files with 63 additions and 4 deletions

View File

@@ -13,7 +13,7 @@ mod set4;
mod utils; mod utils;
fn main() { fn main() {
const RUN_ALL: bool = true; const RUN_ALL: bool = false;
if RUN_ALL { if RUN_ALL {
set1::challenge1(); set1::challenge1();
set1::challenge2(); set1::challenge2();
@@ -42,7 +42,8 @@ fn main() {
set4::challenge25(); set4::challenge25();
set4::challenge26(); set4::challenge26();
set4::challenge27(); set4::challenge27();
set4::challenge28();
} else { } else {
set4::challenge27(); set4::challenge28();
} }
} }

View File

@@ -1,4 +1,4 @@
use crate::{bytes::Bytes, ctr, parser, utils}; use crate::{bytes::Bytes, cbc, ctr, parser, utils};
pub fn challenge25() { pub fn challenge25() {
let cipher = utils::read_base64("data/25.txt"); let cipher = utils::read_base64("data/25.txt");
@@ -80,5 +80,63 @@ pub fn challenge26() {
} }
pub fn challenge27() { pub fn challenge27() {
println!("[xxxx] Challenge 27: tbd"); fn encrypt(key: &Bytes) -> Bytes {
// AES-CBC(P_1, P_2, P_3) -> C_1, C_2, C_3
let mut ct = Bytes::from_utf8("comment1=cooking%20MCs;userdata=secretsaucenouse");
ct.pad_pkcs7(16);
cbc::encrypt(&key, &key, &ct)
}
fn decrypt(key: &Bytes, cipher: &Bytes) -> Result<Bytes, Bytes> {
// The CBC code from exercise 16 encrypts a URL string. Verify each byte
// of the plaintext for ASCII compliance (ie, look for high-ASCII
// values). Noncompliant messages should raise an exception or return an
// error that includes the decrypted plaintext (this happens all the
// time in real systems, for what it's worth).
let mut cleartext = cbc::decrypt(&key, &key, &cipher);
cleartext.remove_pkcs7(16);
match std::str::from_utf8(&cleartext.0) {
Ok(_) => Ok(cleartext),
Err(_) => Err(cleartext),
}
}
fn modify(cipher: &Bytes) -> Bytes {
// C_1, C_2, C_3 -> C_1, 0, C_1
let c1 = cipher.get_block(0, 16).0;
let mut modified = c1.to_vec();
modified.append(&mut vec![0; 16]);
modified.append(&mut c1.to_vec());
Bytes(modified)
}
fn recover_key(plaintext: &Bytes) -> Bytes {
// P'_1 XOR P'_3
let block_size = 16;
Bytes(utils::xor(
&plaintext.get_block(0, block_size).0,
&plaintext.get_block(2, block_size).0,
))
}
let key = Bytes::random(16);
// Use your code to encrypt a message that is at least 3 blocks long:
let cipher = encrypt(&key);
// Modify the message (you are now the attacker):
let cipher = modify(&cipher);
let plaintext = decrypt(&key, &cipher);
// As the attacker, recovering the plaintext from the error, extract the key:
let recovered_key = match plaintext {
Ok(plaintext) => panic!("Ok: {:?}", plaintext.to_utf8()),
Err(plaintext) => recover_key(&plaintext),
};
assert_eq!(key, recovered_key);
println!("[okay] Challenge 27: recovered key successfully");
}
pub fn challenge28() {
println!("[xxxx] Challenge 28: TBD");
} }