Detect ECB via duplicated chunks instead of Hemming distance as I should have done in the first place.

This commit is contained in:
2022-04-27 10:34:40 -04:00
parent 06af500a52
commit 994da471c4
3 changed files with 35 additions and 23 deletions

View File

@@ -57,11 +57,9 @@ pub fn challenge11() {
// Write a function that encrypts data under an unknown key --- that is, a
// function that generates a random key and encrypts under it.
let key = Bytes(random_bytes(16));
// Under the hood, have the function append 5-10 bytes (count chosen randomly)
// before the plaintext and 5-10 bytes after the plaintext.
let _padded_data = pad_data(data.to_vec());
let padded_data = Bytes(data.to_vec());
let padded_data = pad_data(data.to_vec());
// Now, have the function choose to encrypt under ECB 1/2 the time, and under CBC
// the other half (just use random IVs each time for CBC). Use rand(2) to decide
// which to use.
@@ -69,9 +67,8 @@ pub fn challenge11() {
let (data, encryption_type) = if zero_or_one == 1 {
(ecb::encrypt(&key, &padded_data), EncryptionType::ECB)
} else {
// let iv = Bytes(random_bytes(16));
// (cbc::encrypt(&key, &iv, &padded_data), EncryptionType::CBC)
(Bytes(random_bytes(2876)), EncryptionType::CBC)
let iv = Bytes(random_bytes(16));
(cbc::encrypt(&key, &iv, &padded_data), EncryptionType::CBC)
};
(data, encryption_type)
}
@@ -80,22 +77,7 @@ pub fn challenge11() {
// Detect the block cipher mode the function is using each time. You should end up
// with a piece of code that, pointed at a block box that might be encrypting ECB
// or CBC, tells you which one is happening.
fn rate(Bytes(v): &Bytes, size: usize) -> u32 {
let mut rating = 0;
let chunks: Vec<&[u8]> = v.chunks(size).collect();
let mut count = 0;
for i in 0..chunks.len() {
for j in (i + 1)..chunks.len() {
rating +=
Bytes::hemming(&Bytes(chunks[i].to_vec()), &Bytes(chunks[j].to_vec()));
count += 1;
}
}
rating / count
}
let rating = rate(&data, 16);
if rating < 50 {
if data.has_duplicated_cycle(16) {
EncryptionType::ECB
} else {
EncryptionType::CBC
@@ -103,6 +85,11 @@ pub fn challenge11() {
}
fn run_oracle(count: usize) {
// I struggled for a while to understand how the detection oracle can
// work. The issue is that if we provide a random text to encrypt, we
// won't be able to use duplicated blocks as a method for detecting the
// cipher. I don't think there is a way around that, but if we can choose
// the plaintext it becomes trivial.
let text = Bytes::from_utf8("aaaabbbbccccddddaaaabbbbccccddddaaaabbbbccccdddd");
let mut correct: usize = 0;
for _ in 0..count {