1
mirror of https://github.com/hashcat/hashcat synced 2024-11-28 05:21:38 +01:00
hashcat/tools/test_modules/m23002.pm
2020-05-31 10:36:41 +02:00

194 lines
3.5 KiB
Perl

#!/usr/bin/env perl
##
## Author......: See docs/credits.txt
## License.....: MIT
##
use strict;
use warnings;
use Digest::SHA qw (sha1);
use Crypt::CBC;
sub module_constraints { [[0, 256], [-1, -1], [0, 55], [-1, -1], [-1, -1]] }
sub module_generate_hash
{
my $word = shift;
my $salt = shift; # unused since unsalted algo
my $iv = shift;
my $data = shift;
my $file = shift;
my $bit_len = 192;
my $key_len = $bit_len / 8;
my $is_decrypt = defined ($data);
my $padding = "none"; # for decryption we need this to "keep" the padding bytes
if ($is_decrypt == 0)
{
$padding = "standard";
# generate some additional random hash data:
my $iv_len = random_number (1, 16);
$iv = random_bytes ($iv_len);
$data = random_bytes (128);
$file = random_lowercase_string (random_number (1, 16));
$file .= ".txt";
}
my $iv_mod = $iv;
$iv_mod .= "\x00" x (16 - length ($iv_mod));
# start of main algo:
my $digest = sha1 ($word);
my $buf = "";
for (my $i = 0; $i < 20; $i++)
{
$buf .= chr (ord (substr ($digest, $i, 1)) ^ ord ("\x36")); # or just ^ 0x36
}
$buf .= "\x36" x 44;
my $key = sha1 ($buf);
$buf = "";
for (my $i = 0; $i < 20; $i++)
{
$buf .= chr (ord (substr ($digest, $i, 1)) ^ ord ("\x5c")); # or just ^ 0x36
}
$buf .= "\x5c" x 44;
# final key:
$key = $key . sha1 ($buf);
$key = substr ($key, 0, $key_len);
my $aes = Crypt::CBC->new ({
cipher => "Crypt::Rijndael",
key => $key,
iv => $iv_mod,
keysize => $key_len,
literal_key => 1,
header => "none",
padding => $padding,
});
if ($is_decrypt == 0)
{
$data = $aes->encrypt ($data);
}
else
{
my $data_decrypted = $aes->decrypt ($data);
# the password is wrong if the decrypted data does not have the expected padding bytes:
if (substr ($data_decrypted, -16) ne "\x10" x 16)
{
$data = "fake"; # fake data
}
}
my $iv_padded = $iv;
if (length ($iv_padded) < 12)
{
$iv_padded .= "\x00" x (12 - length ($iv_padded));
}
my $hash = sprintf ("\$zip3\$*0*1*%i*0*%s*%s*0*0*0*%s", $bit_len, unpack ("H*", $iv_padded), unpack ("H*", $data), $file);
return $hash;
}
sub module_verify_hash
{
my $line = shift;
return unless (substr ($line, 0, 11) eq "\$zip3\$*0*1*");
my $idx1 = index ($line, ":");
return unless ($idx1 >= 11);
my $hash = substr ($line, 0, $idx1);
my $word = substr ($line, $idx1 + 1);
# bit_len:
$idx1 = index ($hash, "*", 11);
return unless ($idx1 > 0);
my $bit_len = substr ($hash, 11, $idx1 - 11);
$bit_len = int ($bit_len);
return unless ($bit_len == 192);
# unused:
return unless (substr ($hash, $idx1 + 1, 2) eq "0*");
# iv:
my $idx2 = index ($hash, "*", $idx1 + 3);
return unless ($idx2 > 0);
my $iv = substr ($hash, $idx1 + 3, $idx2 - $idx1 - 3);
return unless ($iv =~ m/^[0-9a-fA-F]+$/);
return unless ((length ($iv) % 2) == 0);
# data:
$idx1 = index ($hash, "*", $idx2 + 1);
return unless ($idx1 > 0);
my $data = substr ($hash, $idx2 + 1, $idx1 - $idx2 - 1);
return unless ($data =~ m/^[0-9a-fA-F]+$/);
return unless ((length ($data) % 2) == 0);
# unused:
return unless (substr ($hash, $idx1 + 1, 6) eq "0*0*0*");
# file:
my $file = substr ($hash, $idx1 + 7);
# convert to hex:
$iv = pack ("H*", $iv);
$data = pack ("H*", $data);
my $word_packed = pack_if_HEX_notation ($word);
my $new_hash = module_generate_hash ($word_packed, "", $iv, $data, $file);
return ($new_hash, $word);
}
1;