The final challenge in our first Cryptopals set is to detect an AES-encrypted string that is potentially using ECB mode:
In this file are a bunch of hex-encoded ciphertexts.
One of them has been encrypted with ECB.
Detect it.
Remember, ECB mode means every identical block of plaintext produces an identical block of ciphertext. We can attempt to detect the use of ECB mode by iterating through every 16-byte block in our plaintext looking for duplicates.
We’ll write a routine that operates on our handy Bytes
object. It will return a Boolean flag as to whether or not the wrapped string of bytes contains duplicates.
public function containsDuplicates(int $blockSize = 16): bool
{
$blocks = [];
for ($i = 0; $i < $this->length(); $i += $blockSize) {
$block = substr($this->bytes, $i, $blockSize);
if (in_array($block, $blocks)) {
return true;
}
array_push($blocks, $block);
}
return false;
}
Now that we can find duplicate blocks, we can iterate over the candidate ciphertexts in the provided file.
$foundECB = false;
$fp = fopen('8.txt', 'r');
if ($fp) {
while(($buffer = fgets($fp, 4096)) !== false) {
$line = trim(preg_replace('/\s+/', '', $buffer));
$ciphertext = new Bytes($line);
if ($ciphertext->containsDuplicates()) {
print '-> ' . $ciphertext->asHex() . PHP_EOL;
$foundECB = true;
}
}
print $foundECB ? 'Possibe ECB in the above!' : 'No ECB' . PHP_EOL;
fclose($fp);
exit(0);
}
print 'fopen Error';
exit(1);
I did promise that abstracting things into our Bytes
object all those challenges again would come in handy, didn’t I? This is a pretty smooth implementation and, while it could be even more concise, does the job with little fuss.
Keep that class definition around, as it’s going to remain useful when we enter Set 2, which is all about block ciphers!