ETOOBUSY 🚀 minimal blogging for the impatient
Cryptopals 4 - Detect single-character XOR
TL;DR
There are two things I appreciate a lot about Cryptopals:
- it provides a path, usually building upon the previous step(s) to assemble/discover something new and more powerful;
- it tells you what to do but not necessarily how. There’s a lot of places around for the how and it’s interesting to try and find a how by ourselves, right?
In this challenge, the suggestion is to use the single_char_decrypt
function from the previous one, and build a higher level artificial
intelligence to sift through several candidate ciphertext and spot the
one that’s been encoded with that basic technique.
I thought of the simplest way of doing it: collect both the decrypted
text and the score, then get the best among all that have a non-0
score. To this regard, the fact that single_char_decrypt
from last
post provides us the score too (when called in list context) helps a lot
😅. Again, it’s been migrated in the Cryptopals
helper module to avoid
cluttering today’s code.
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use English '-no_match_vars';
use CryptoPals qw< decode_base16 single_char_decrypt >;
# keep track of best solution and associated best score, to get the best
my ($best, $best_score);
open my $fh, '<:raw', '4.txt' or die "open('4.txt'): $OS_ERROR\n";
while (<$fh>) {
s{\s+}{}gmxs; # spaces don't belong to the hex encoding
# try to decrypt this candidate line, collect score on the way
my ($candidate, $score) = single_char_decrypt(decode_base16($_));
next unless $score; # no reason to look for non-0 scores
# usual incantation to select the best by comparison
($best, $best_score) = ($candidate, $score)
if ! $best_score || $best_score < $score;
}
say "Best found: <$best>";
The code pretty much explains itself and… works!
Stay safe and secure!