Cryptopals 7 - AES in ECB mode


Challenge 7 in Cryptopals.

After a little detour to build our own AES toy implementation, we’re finally ready for addressing Challenge 7.

We have the primitive to do single-block operations, which is a good start. On the other hand, an operation mode is more than this, because it allows us to operate on a bunch of data that might be less than, or more than, a single block, usually by specifying some additional constraints:

  • a padding function, i.e. how data is expanded to cover an integer number of blocks, and
  • how each block is passed through the AES encryption routine.

There is much more to read in page Block cipher mode of operation.

For the Electronic Code Book (ECB) mode, the padding function is the one that comes from standard PKCS#7 (actually, what it has become today RFC 5652):

sub pkcs7_pad ($input, $blen) {
   die "unsupported block length\n" if $blen >= 256;
   my $ilen = length $input;
   my $npad = $blen - ($ilen % $blen);
   return $input . (chr($npad) x $npad);

Next, AES-ECB tells us that encryption is done by applying AES on each block separately, independently and deterministically. Decryption, of course, goes the other way around.

sub aes_ecb_encrypt ($plaintext, $key) {
    my $be = block_encrypter($key);
    my $padded = pkcs7_pad($plaintext, 16);
    my @chunks;
    while (length $padded) {
        push @chunks, $be->(substr $padded, 0, 16, '');
    return join '', @chunks;

This said, we can toss away the toy, which is slow, and use CryptX, which is faster:

sub aes_ecb_encrypt ($plaintext, $key) {
   state $ecb = Crypt::Mode::ECB->new('AES');
   $ecb->encrypt($plaintext, $key);

sub aes_ecb_decrypt ($ciphertext, $key) {
   state $ecb = Crypt::Mode::ECB->new('AES');
   $ecb->decrypt($ciphertext, $key);

Much ado about nothing? Well I argue that no, it’s not that case. It’s been very useful (to me, at least) to get the hang on the algorithm, but I see no reason why I shouldn’t use the faster implementation from now on, because we’re not getting into the details of single-block ciphering any more.

So, finally, the solution to Challenge 7 is:

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use CryptoPals qw< slurp_base64 aes_ecb_decrypt >;

my $ciphertext = slurp_base64(shift // '7.txt');

say aes_ecb_decrypt($ciphertext, $key);

You know what slurp_base64 does, right?

Unsurprisingly, it’s the same output as that of the previous challenge!

Stay safe and secure!

Comments? Octodon, , GitHub, Reddit, or drop me a line!