This is Challenge 8 of Cryptopals challenges implemented in Rust language.
Context
We're given a file which lists a bunch of hex-encoded ciphertexts. One of these texts is encrypted with AES-128 in ECB mode. We have to detect which one is it. I recommend to see Challenge 7 if you haven't yet.
Remember that AES-128 divides message into 16 byte blocks before encrypting. In ECB mode each block is encrypted seperately. Therefore - the same 16 byte plaintext block will always produce the same 16 byte ciphertext. We'll exploit this property of ECB mode.
Given the ciphertext, the more number of identical 16-byte blocks, the higher the probability of it having encrypted in ECB mode. Because that means (most probably) the text message contained some identical phrases/blocks that were repeated. And these repeated phrases/blocks encrypted to exactly same ciphertext because of nature of ECB.
...and there was yellow submarine...yellow submarine sank in... |------ECB-----| |------ECB-----| ...a733hj32hbczxsbv...a733hj32hbczxsbv....
Code
In code we basically loop through each hex string. Convert it to bytes then divide these bytes into 16-byte blocks. Then count number of identical blocks among these. The hex-string that corresponds to max number of identical blocks is encrypted in ECB mode.
use hex; use std::collections::HashSet; use std::fs::File; use std::io::{BufRead, BufReader}; pub fn detect_aes_ecb_encryption(path: &str) -> (usize, usize) { let file = File::open(path).expect("Error reading file!"); let lines = BufReader::new(file).lines(); let mut i_line: usize = 0; let mut max_identical_blocks: usize = 0; let mut n_identical_blocks: usize; for (i, line) in lines.enumerate() { let hex = line.unwrap(); // Hex line to bytes vec let bytes = hex::decode(hex).unwrap(); // Divide bytes into 16 byte blocks (&[u8] blocks) let blocks: Vec<_> = bytes.chunks_exact(16).collect(); // Get unique blocks let unique_blocks: HashSet<_> = blocks.iter().cloned().collect(); // No. of identical blocks detected n_identical_blocks = blocks.len() - unique_blocks.len(); // Cipher containing most identical blocks is more likely to be // ECB mode encrypted if n_identical_blocks > max_identical_blocks { max_identical_blocks = n_identical_blocks; i_line = i; } } (i_line, max_identical_blocks) }
And this is it. We've concluded Set 1.
See code on Github
Find me on:
Twitter - @heyNvN
Top comments (0)