Cryptopals 19 - Break fixed-nonce CTR mode using substitutions (part 1)

TL;DR

Challenge 19 in Cryptopals, part 1.

So we’re at something serious:

Break fixed-nonce CTR mode using substitutions

I’m quite positive that I didn’t get the challenge right. I mean, I managed to decrypt the stuff, but the way I did is basically the same I used for the following challenge. Maybe I didn’t get that right, who knows?

Anyway, this challenge is kind of heavy, so let’s get started: encryption. As a courtesy, I think, we’re given encoded (but not encrypted) strings, that we have to encrypt ourselves with our new CTR toy, just to have the fun of breaking it with our own shiny random key.

So here we go for generating the encrypted strings:

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';

use List::Util qw< min max >;
use CryptoPals qw< random_key ctr_mode_encrypt block_encrypter
   decode_base64 encode_base64 >;

$|++;
my $be = block_encrypter(random_key());
my $nonce = "\x00" x 8;
my @lengths;
while (<DATA>) {
   my $plaintxt = decode_base64($_);
   my $lp = length $plaintxt;
   push @lengths, $lp;
   printf {*STDERR} '%3d  ', $lp;
   print {*STDOUT} encode_base64(ctr_mode_encrypt($be, $nonce, $plaintxt));
}

print {*STDERR} min(@lengths), ' .. ', max(@lengths), "\n";


__DATA__
SSBoYXZlIG1ldCB0aGVtIGF0IGNsb3NlIG9mIGRheQ==
Q29taW5nIHdpdGggdml2aWQgZmFjZXM=
RnJvbSBjb3VudGVyIG9yIGRlc2sgYW1vbmcgZ3JleQ==
RWlnaHRlZW50aC1jZW50dXJ5IGhvdXNlcy4=
SSBoYXZlIHBhc3NlZCB3aXRoIGEgbm9kIG9mIHRoZSBoZWFk
T3IgcG9saXRlIG1lYW5pbmdsZXNzIHdvcmRzLA==
T3IgaGF2ZSBsaW5nZXJlZCBhd2hpbGUgYW5kIHNhaWQ=
UG9saXRlIG1lYW5pbmdsZXNzIHdvcmRzLA==
QW5kIHRob3VnaHQgYmVmb3JlIEkgaGFkIGRvbmU=
T2YgYSBtb2NraW5nIHRhbGUgb3IgYSBnaWJl
VG8gcGxlYXNlIGEgY29tcGFuaW9u
QXJvdW5kIHRoZSBmaXJlIGF0IHRoZSBjbHViLA==
QmVpbmcgY2VydGFpbiB0aGF0IHRoZXkgYW5kIEk=
QnV0IGxpdmVkIHdoZXJlIG1vdGxleSBpcyB3b3JuOg==
QWxsIGNoYW5nZWQsIGNoYW5nZWQgdXR0ZXJseTo=
QSB0ZXJyaWJsZSBiZWF1dHkgaXMgYm9ybi4=
VGhhdCB3b21hbidzIGRheXMgd2VyZSBzcGVudA==
SW4gaWdub3JhbnQgZ29vZCB3aWxsLA==
SGVyIG5pZ2h0cyBpbiBhcmd1bWVudA==
VW50aWwgaGVyIHZvaWNlIGdyZXcgc2hyaWxsLg==
V2hhdCB2b2ljZSBtb3JlIHN3ZWV0IHRoYW4gaGVycw==
V2hlbiB5b3VuZyBhbmQgYmVhdXRpZnVsLA==
U2hlIHJvZGUgdG8gaGFycmllcnM/
VGhpcyBtYW4gaGFkIGtlcHQgYSBzY2hvb2w=
QW5kIHJvZGUgb3VyIHdpbmdlZCBob3JzZS4=
VGhpcyBvdGhlciBoaXMgaGVscGVyIGFuZCBmcmllbmQ=
V2FzIGNvbWluZyBpbnRvIGhpcyBmb3JjZTs=
SGUgbWlnaHQgaGF2ZSB3b24gZmFtZSBpbiB0aGUgZW5kLA==
U28gc2Vuc2l0aXZlIGhpcyBuYXR1cmUgc2VlbWVkLA==
U28gZGFyaW5nIGFuZCBzd2VldCBoaXMgdGhvdWdodC4=
VGhpcyBvdGhlciBtYW4gSSBoYWQgZHJlYW1lZA==
QSBkcnVua2VuLCB2YWluLWdsb3Jpb3VzIGxvdXQu
SGUgaGFkIGRvbmUgbW9zdCBiaXR0ZXIgd3Jvbmc=
VG8gc29tZSB3aG8gYXJlIG5lYXIgbXkgaGVhcnQs
WWV0IEkgbnVtYmVyIGhpbSBpbiB0aGUgc29uZzs=
SGUsIHRvbywgaGFzIHJlc2lnbmVkIGhpcyBwYXJ0
SW4gdGhlIGNhc3VhbCBjb21lZHk7
SGUsIHRvbywgaGFzIGJlZW4gY2hhbmdlZCBpbiBoaXMgdHVybiw=
VHJhbnNmb3JtZWQgdXR0ZXJseTo=
QSB0ZXJyaWJsZSBiZWF1dHkgaXMgYm9ybi4=

We already saw all functions, so it should be pretty clear what’s going on.

We’re using Perl’s ability to include stuff in the program that can be read with the DATA filehandle, so that we keep the clutter out of the way. I’m not always a fan of this technique, to be honest, but it’s perfect for this size and purpose.

There’s a bit of printing of lengths on STDERR because strings have different sizes and I wanted to figure out the minimum and maximum ones, but it’s otherwise not needed.

I saved the output to a file 19.enc and that is what we’re going to look at shortly.

Stay safe and secure!


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