Cryptopals Diversion 1 - A counter

TL;DR

A little detour that will help with Challenge 18 in Cryptopals.

Cryptopals challenge 18 is about implementing counter mode, so we will obviously need a counter. In our case, a 64 bits counter.

I’ve always been aware to have lived - and still live - in a technological bubble where things seem to be fixed and forever - endianness, number of available bits for integers, etc. - but they actually aren’t. So I waste my time implementing solutions to sub-problems that will not arise in real world - if anything, because I’m studying something else.

Or am I? This diversion is a nice venture into the how would I approach building a 64 bits counter if I only had 32 bits arithmetics? - so here we go.

The approach is to keep it simple and safe, at the expense of efficiency. I hope only efficiency, anyway. So we have 32 bits arithmetics or more, and use it limited to 16 bits arithmetics: we will never overflow, right?

sub counter_64bits ($init = '') { # 4x 16-bits integers, little-endian
   my @counter = (0) x 4;
   @counter = unpack 'v4', substr(("\x00\x00" x 4) . $init, -8, 8);
   return sub {
      my $retval = pack 'v4', @counter;
      my $i = 0;
      while ($i < 4) {
         last if ++$counter[$i] <= 0xFFFF;
         $counter[$i++] = 0;
      }
      return $retval;
   };
}

Variable @counter keeps four integers that we will cap at 16 bits; whenever we go beyond, the counter is reset and the next integer is incremented. The last carry, if any, will be just lost - so our counter will happily pass from 0xFFFFFFFFFFFFFFFF to 0x0.

We’re forcing little-endianness as per instructions in the text. This means that we use v4 to aggregate the four integers as four little-endian 16-bits friends. Or disaggregate them, if we insist on passing an initialization value.

The counter is used as an iterator function. You first get your iterator, that is a sub reference:

my $counter_iterator = counter_64bits();

and then run the function whenever a new 64-bits encoded counter is needed:

my $nonce = "\x00" x 8;
while ('necessary') {
    my $counter = $counter_iterator->();
    my $xor_bits = aes_block_encryption($key, $nonce . $counter);
    ...
}

Stay safe and secure!


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