Data-ChipsChallenge
view release on metacpan or search on metacpan
lib/Data/ChipsChallenge.pm view on Meta::CPAN
# my $x = 0;
# for (my $i = 0; $i < scalar(@flat); $i++) {
# $x++;
# my $deb = sprintf("%02x", unpack("C", $flat[$i]));
# print "$deb ";
# print "\n" if $x >= 32;
# $x = 0 if $x >= 32;
# }
# print "\n";
my $i = 0;
while ($i < 1024) {
my $byte = $flat[$i];
my $deb1 = sprintf("%02x", unpack("C", $byte));
# print "Byte: $deb1\n";
# See if the next 5 bytes are the same.
my $copies = 0;
for (my $j = 0; ($i + $j) < scalar(@flat); $j++) {
my $compare = $flat[$i + $j];
if ($byte eq $compare) {
# print "Byte $i matches byte " . ($i+$j) . "\n";
$copies++;
last if $copies >= 255;
}
else {
last;
}
}
# Can we compress this?
if ($copies >= 4) {
# Yes! See how many copies there are exactly.
# print "Compress byte $deb1 by $copies times\n";
$i += $copies;
my $len = pack("C", $copies);
push (@compressed,
$ff,
$len,
$byte,
);
}
else {
$i++;
push (@compressed, $byte);
}
}
# Return the compressed binary.
my $bin = join("",@compressed);
return $bin;
}
=head2 decode_password (bin RAW_BINARY)
Given the encoded level password in raw binary (4 bytes followed by a null byte),
this function returns the 4 ASCII byte password in clear text. This is the password
you'd type into Chip's Challenge.
Passwords are decoded by XORing the values in the raw binary by hex C<0x99>,
if you're curious.
=cut
sub decode_password {
my ($self,$data) = @_;
my @chars = split(//, $data, 5);
# Decode each character.
my $pass = '';
for (my $i = 0; $i < 4; $i++) {
my $dec = unpack("C",$chars[$i]);
my $hex = uc(sprintf("%02x",$dec));
# Decode it with XOR 0x99
my $xor = $dec ^ 0x99;
my $chr = chr($xor);
$pass .= $chr;
}
return $pass;
}
=head2 encode_password (string PASSWORD)
Given the plain text password C<PASSWORD>, it encodes it and returns it as
a 5 byte binary string (including the trailing null byte).
=cut
sub encode_password {
my ($self,$pass) = @_;
my @chars = split(//, $pass, 4);
# Encode each character.
my $bin = '';
for (my $i = 0; $i < 4; $i++) {
my $dec = unpack("C", $chars[$i]);
my $hex = sprintf("%02x",$dec);
# XOR it with 0x99
my $xor = hex("0x$hex") ^ 0x99;
$bin .= pack("C",$xor);
}
$bin .= chr(0x00);
# try...
my $plain = $self->decode_password($bin);
return $bin;
}
=head2 random_password
Returns a random 4-letter password.
=cut
( run in 1.561 second using v1.01-cache-2.11-cpan-2398b32b56e )