mirror of
https://github.com/hashcat/hashcat.git
synced 2024-12-22 22:58:30 +00:00
Add unit tests for multiple modules
13800, 13900, 14400, 14700, 14800, 14900, 15000, 15100 & 15200
This commit is contained in:
parent
eb4f5d82d1
commit
825c977ca4
49
tools/test_modules/m13800.pm
Normal file
49
tools/test_modules/m13800.pm
Normal file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha256_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 255], [256, 256], [0, 27], [256, 256], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $word_utf16le = encode ("UTF-16LE", $word);
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $digest = sha256_hex ($word_utf16le . $salt_bin);
|
||||
|
||||
my $hash = sprintf ("%s:%s", $digest, $salt);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $salt;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
45
tools/test_modules/m13900.pm
Normal file
45
tools/test_modules/m13900.pm
Normal file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha1_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 255], [9, 9], [0, 46], [9, 9], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha1_hex ($salt . sha1_hex ($salt . sha1_hex ($word)));
|
||||
|
||||
my $hash = sprintf ("%s:%s", $digest, $salt);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $salt;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
52
tools/test_modules/m14400.pm
Normal file
52
tools/test_modules/m14400.pm
Normal file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha1_hex);
|
||||
|
||||
sub module_constraints { [[0, 235], [20, 20], [0, 35], [20, 20], [0, 55]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $begin = "--" . $salt . "--";
|
||||
my $end = "--" . $word . "----";
|
||||
|
||||
my $digest = sha1_hex ($begin . $end);
|
||||
|
||||
for (my $round = 1; $round < 10; $round++)
|
||||
{
|
||||
$digest = sha1_hex ($begin . $digest . $end);
|
||||
}
|
||||
|
||||
my $hash = sprintf ("%s:%s", $digest, $salt);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $salt;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
195
tools/test_modules/m14700.pm
Normal file
195
tools/test_modules/m14700.pm
Normal file
@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Crypt::Mode::ECB;
|
||||
|
||||
sub module_constraints { [[0, 255], [40, 40], [0, 55], [40, 40], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iterations = shift // 10000;
|
||||
my $wpky_param = shift;
|
||||
|
||||
my $pbkdf2 = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'),
|
||||
iterations => $iterations,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
$salt = pack ("H*", $salt);
|
||||
|
||||
my $key = $pbkdf2->PBKDF2 ($salt, $word);
|
||||
|
||||
my $ITUNES_BACKUP_KEY = 12008468691120727718;
|
||||
|
||||
my $WPKY = "\x00" x 40;
|
||||
|
||||
if (defined $wpky_param)
|
||||
{
|
||||
my ($A, $R) = itunes_aes_unwrap ($key, $wpky_param);
|
||||
|
||||
if ($A == $ITUNES_BACKUP_KEY)
|
||||
{
|
||||
$WPKY = itunes_aes_wrap ($key, $A, $R);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
my $max_number = 18446744073709551615; # 0xffffffffffffffff
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < 4; $i++)
|
||||
{
|
||||
$R[$i] = random_number (0, $max_number);
|
||||
}
|
||||
|
||||
$WPKY = itunes_aes_wrap ($key, $ITUNES_BACKUP_KEY, \@R);
|
||||
}
|
||||
|
||||
my $hash = sprintf ("\$itunes_backup\$*9*%s*%i*%s**", unpack ("H*", $WPKY), $iterations, unpack ("H*", $salt));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my ($signature, $version, $wpky_encoded, $iterations, $salt, undef, undef) = split ('\*', $hash);
|
||||
|
||||
return unless ($signature eq '$itunes_backup$');
|
||||
return unless ($version eq '9');
|
||||
return unless length ($wpky_encoded) == 80;
|
||||
return unless defined $iterations;
|
||||
return unless defined $salt;
|
||||
|
||||
my $wpky = pack ("H*", $wpky_encoded);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iterations, $wpky);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
sub itunes_aes_wrap
|
||||
{
|
||||
my $key = shift;
|
||||
my $A = shift;
|
||||
my $R_l = shift;
|
||||
|
||||
my $k = scalar (@$R_l);
|
||||
my $n = $k + 1;
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < $n; $i++)
|
||||
{
|
||||
$R[$i] = @$R_l[$i];
|
||||
}
|
||||
|
||||
# AES mode ECB
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
# main wrap loop
|
||||
|
||||
my ($i, $j, $a);
|
||||
|
||||
for ($j = 0; $j <= 5; $j++)
|
||||
{
|
||||
for ($i = 1, $a = 0; $i <= $k; $i++, $a++)
|
||||
{
|
||||
my $input;
|
||||
|
||||
$input = pack ("Q>", $A);
|
||||
$input .= pack ("Q>", $R[$a]);
|
||||
|
||||
my $t = $m->encrypt ($input, $key);
|
||||
|
||||
$A = unpack ("Q>", substr ($t, 0, 8));
|
||||
$A ^= $k * $j + $i;
|
||||
|
||||
$R[$a] = unpack ("Q>", substr ($t, 8, 8));
|
||||
}
|
||||
}
|
||||
|
||||
my $WPKY = pack ("Q>", $A);
|
||||
|
||||
for (my $i = 0; $i < $k; $i++)
|
||||
{
|
||||
$WPKY .= pack ("Q>", $R[$i]);
|
||||
}
|
||||
|
||||
return $WPKY;
|
||||
}
|
||||
|
||||
sub itunes_aes_unwrap
|
||||
{
|
||||
my $key = shift;
|
||||
my $WPKY = shift;
|
||||
|
||||
my @B;
|
||||
|
||||
for (my $i = 0; $i < length ($WPKY) / 8; $i++)
|
||||
{
|
||||
$B[$i] = unpack ("Q>", substr ($WPKY, $i * 8, 8));
|
||||
}
|
||||
|
||||
my $n = scalar (@B);
|
||||
my $k = $n - 1;
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < $k; $i++)
|
||||
{
|
||||
$R[$i] = $B[$i + 1];
|
||||
}
|
||||
|
||||
# AES mode ECB
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
# main unwrap loop
|
||||
|
||||
my $A = $B[0];
|
||||
|
||||
my ($i, $j, $a);
|
||||
|
||||
for ($j = 5; $j >= 0; $j--)
|
||||
{
|
||||
for ($i = $k, $a = $k - 1; $i > 0; $i--, $a--)
|
||||
{
|
||||
my $input;
|
||||
|
||||
$input = pack ("Q>", $A ^ ($k * $j + $i));
|
||||
$input .= pack ("Q>", $R[$a]);
|
||||
|
||||
my $t = $m->decrypt ($input, $key);
|
||||
|
||||
$A = unpack ("Q>", substr ($t, 0, 8));
|
||||
$R[$a] = unpack ("Q>", substr ($t, 8, 8));
|
||||
}
|
||||
}
|
||||
|
||||
return ($A, \@R);
|
||||
}
|
||||
|
||||
1;
|
213
tools/test_modules/m14800.pm
Normal file
213
tools/test_modules/m14800.pm
Normal file
@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Crypt::Mode::ECB;
|
||||
|
||||
sub module_constraints { [[0, 255], [40, 40], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iterations = shift // 10000;
|
||||
my $wpky_param = shift;
|
||||
my $DPIC = shift // 1000;
|
||||
my $DPSL = shift // random_bytes (20);
|
||||
|
||||
my $pbkdf2 = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'),
|
||||
iterations => $iterations,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
$salt = pack ("H*", $salt);
|
||||
|
||||
my $ITUNES_BACKUP_KEY = 12008468691120727718;
|
||||
|
||||
my $WPKY = "\x00" x 40;
|
||||
|
||||
my $pbkdf2x = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2'),
|
||||
iterations => $DPIC,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
my $key_dpsl = $pbkdf2x->PBKDF2 ($DPSL, $word);
|
||||
|
||||
my $key = $pbkdf2->PBKDF2 ($salt, $key_dpsl);
|
||||
|
||||
if (defined $wpky_param)
|
||||
{
|
||||
my ($A, $R) = itunes_aes_unwrap ($key, $wpky_param);
|
||||
|
||||
if ($A == $ITUNES_BACKUP_KEY)
|
||||
{
|
||||
$WPKY = itunes_aes_wrap ($key, $A, $R);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
my $max_number = 18446744073709551615; # 0xffffffffffffffff
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < 4; $i++)
|
||||
{
|
||||
$R[$i] = random_number (0, $max_number);
|
||||
}
|
||||
|
||||
$WPKY = itunes_aes_wrap ($key, $ITUNES_BACKUP_KEY, \@R);
|
||||
}
|
||||
|
||||
my $hash = sprintf ("\$itunes_backup\$*10*%s*%i*%s*%i*%s", unpack ("H*", $WPKY), $iterations, unpack ("H*", $salt), $DPIC, unpack ("H*", $DPSL));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my ($signature, $version, $wpky_encoded, $iterations, $salt, $dpic, $dpsl_encoded) = split ('\*', $hash);
|
||||
|
||||
return unless ($signature eq '$itunes_backup$');
|
||||
return unless ($version eq '10');
|
||||
return unless length ($wpky_encoded) == 80;
|
||||
return unless defined $iterations;
|
||||
return unless defined $salt;
|
||||
return unless defined $dpic;
|
||||
return unless defined $dpsl_encoded;
|
||||
|
||||
my $wpky = pack ("H*", $wpky_encoded);
|
||||
my $dpsl = pack ("H*", $dpsl_encoded);
|
||||
|
||||
$iterations = int ($iterations);
|
||||
|
||||
$dpic = int ($dpic);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iterations, $wpky, $dpic, $dpsl);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
sub itunes_aes_wrap
|
||||
{
|
||||
my $key = shift;
|
||||
my $A = shift;
|
||||
my $R_l = shift;
|
||||
|
||||
my $k = scalar (@$R_l);
|
||||
my $n = $k + 1;
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < $n; $i++)
|
||||
{
|
||||
$R[$i] = @$R_l[$i];
|
||||
}
|
||||
|
||||
# AES mode ECB
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
# main wrap loop
|
||||
|
||||
my ($i, $j, $a);
|
||||
|
||||
for ($j = 0; $j <= 5; $j++)
|
||||
{
|
||||
for ($i = 1, $a = 0; $i <= $k; $i++, $a++)
|
||||
{
|
||||
my $input;
|
||||
|
||||
$input = pack ("Q>", $A);
|
||||
$input .= pack ("Q>", $R[$a]);
|
||||
|
||||
my $t = $m->encrypt ($input, $key);
|
||||
|
||||
$A = unpack ("Q>", substr ($t, 0, 8));
|
||||
$A ^= $k * $j + $i;
|
||||
|
||||
$R[$a] = unpack ("Q>", substr ($t, 8, 8));
|
||||
}
|
||||
}
|
||||
|
||||
my $WPKY = pack ("Q>", $A);
|
||||
|
||||
for (my $i = 0; $i < $k; $i++)
|
||||
{
|
||||
$WPKY .= pack ("Q>", $R[$i]);
|
||||
}
|
||||
|
||||
return $WPKY;
|
||||
}
|
||||
|
||||
sub itunes_aes_unwrap
|
||||
{
|
||||
my $key = shift;
|
||||
my $WPKY = shift;
|
||||
|
||||
my @B;
|
||||
|
||||
for (my $i = 0; $i < length ($WPKY) / 8; $i++)
|
||||
{
|
||||
$B[$i] = unpack ("Q>", substr ($WPKY, $i * 8, 8));
|
||||
}
|
||||
|
||||
my $n = scalar (@B);
|
||||
my $k = $n - 1;
|
||||
|
||||
my @R;
|
||||
|
||||
for (my $i = 0; $i < $k; $i++)
|
||||
{
|
||||
$R[$i] = $B[$i + 1];
|
||||
}
|
||||
|
||||
# AES mode ECB
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
# main unwrap loop
|
||||
|
||||
my $A = $B[0];
|
||||
|
||||
my ($i, $j, $a);
|
||||
|
||||
for ($j = 5; $j >= 0; $j--)
|
||||
{
|
||||
for ($i = $k, $a = $k - 1; $i > 0; $i--, $a--)
|
||||
{
|
||||
my $input;
|
||||
|
||||
$input = pack ("Q>", $A ^ ($k * $j + $i));
|
||||
$input .= pack ("Q>", $R[$a]);
|
||||
|
||||
my $t = $m->decrypt ($input, $key);
|
||||
|
||||
$A = unpack ("Q>", substr ($t, 0, 8));
|
||||
$R[$a] = unpack ("Q>", substr ($t, 8, 8));
|
||||
}
|
||||
}
|
||||
|
||||
return ($A, \@R);
|
||||
}
|
||||
|
||||
1;
|
48
tools/test_modules/m14900.pm
Normal file
48
tools/test_modules/m14900.pm
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::Skip32;
|
||||
|
||||
sub module_constraints { [[-1, -1], [-1, -1], [10, 10], [8, 8], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $skip32 = Crypt::Skip32->new ($word);
|
||||
|
||||
my $digest = $skip32->encrypt ($salt_bin);
|
||||
|
||||
my $hash = sprintf ("%08x:%s", unpack ("N*", $digest), $salt);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $salt;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
44
tools/test_modules/m15000.pm
Normal file
44
tools/test_modules/m15000.pm
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha512_hex);
|
||||
|
||||
sub module_constraints { [[0, 255], [64, 64], [0, 55], [64, 64], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha512_hex ($word . $salt);
|
||||
|
||||
my $hash = sprintf ("%s:%s", $digest, $salt);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $salt;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
105
tools/test_modules/m15100.pm
Normal file
105
tools/test_modules/m15100.pm
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha1);
|
||||
use Digest::HMAC qw (hmac);
|
||||
|
||||
sub module_constraints { [[0, 255], [8, 8], [0, 55], [8, 8], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iterations = shift // 20000;
|
||||
my $additional_param = shift;
|
||||
|
||||
my $pbkdf1_salt = sprintf ('%s$sha1$%u', $salt, $iterations);
|
||||
|
||||
my $tmp = hmac ($pbkdf1_salt, $word, \&sha1, 64);
|
||||
|
||||
for (my $r = 1; $r < $iterations; $r++)
|
||||
{
|
||||
$tmp = hmac ($tmp, $word, \&sha1, 64);
|
||||
}
|
||||
|
||||
my $digest = "";
|
||||
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 0, 1))) << 16) | (int (ord (substr ($tmp, 1, 1))) << 8) | (int (ord (substr ($tmp, 2, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 3, 1))) << 16) | (int (ord (substr ($tmp, 4, 1))) << 8) | (int (ord (substr ($tmp, 5, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 6, 1))) << 16) | (int (ord (substr ($tmp, 7, 1))) << 8) | (int (ord (substr ($tmp, 8, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 9, 1))) << 16) | (int (ord (substr ($tmp, 10, 1))) << 8) | (int (ord (substr ($tmp, 11, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 12, 1))) << 16) | (int (ord (substr ($tmp, 13, 1))) << 8) | (int (ord (substr ($tmp, 14, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 15, 1))) << 16) | (int (ord (substr ($tmp, 16, 1))) << 8) | (int (ord (substr ($tmp, 17, 1)))), 4);
|
||||
$digest .= to64 ((int (ord (substr ($tmp, 18, 1))) << 16) | (int (ord (substr ($tmp, 19, 1))) << 8) | 0 , 4);
|
||||
|
||||
## super hackish, but we have no other choice, as this byte is kind of a random byte added to the digest when the hash was created
|
||||
|
||||
if (defined $additional_param)
|
||||
{
|
||||
$digest = substr ($digest, 0, 24) . substr ($additional_param, 24, 4);
|
||||
}
|
||||
|
||||
my $hash = sprintf ("\$sha1\$%d\$%s\$%s", $iterations, $salt, $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my @data = split ('\$', $hash);
|
||||
|
||||
return unless scalar @data == 5;
|
||||
|
||||
shift @data;
|
||||
|
||||
my $signature = shift @data;
|
||||
|
||||
return unless ($signature eq 'sha1');
|
||||
|
||||
my $iterations = shift @data;
|
||||
my $salt = shift @data;
|
||||
my $additional_param = shift @data;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iterations, $additional_param);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
sub to64
|
||||
{
|
||||
my $v = shift;
|
||||
my $n = shift;
|
||||
|
||||
my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
my $ret = "";
|
||||
|
||||
while (($n - 1) >= 0)
|
||||
{
|
||||
$n = $n - 1;
|
||||
|
||||
$ret .= substr ($itoa64, $v & 0x3f, 1);
|
||||
|
||||
$v = $v >> 6;
|
||||
}
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
1;
|
84
tools/test_modules/m15200.pm
Normal file
84
tools/test_modules/m15200.pm
Normal file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Crypt::CBC;
|
||||
|
||||
sub module_constraints { [[0, 255], [32, 32], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iterations = shift // 5000;
|
||||
my $encrypted = shift;
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1');
|
||||
|
||||
my $pbkdf2 = Crypt::PBKDF2->new (
|
||||
hasher => $hasher,
|
||||
iterations => $iterations,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
my $key = $pbkdf2->PBKDF2 ($salt_bin, $word);
|
||||
|
||||
my $cipher = Crypt::CBC->new ({
|
||||
key => $key,
|
||||
cipher => "Crypt::Rijndael",
|
||||
iv => $salt_bin,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32
|
||||
});
|
||||
|
||||
my $data = qq|{
|
||||
"guid" : "00000000-0000-0000-0000-000000000000",
|
||||
"sharedKey" : "00000000-0000-0000-0000-000000000000",
|
||||
"options" : {"pbkdf2_iterations":$iterations,"fee_policy":0,"html5_notifications":false,"logout_time":600000,"tx_display":0,"always_keep_local_backup":false}|;
|
||||
|
||||
unless (defined $encrypted)
|
||||
{
|
||||
$encrypted = unpack ("H*", $cipher->encrypt ($data));
|
||||
}
|
||||
|
||||
my $hash = sprintf ("\$blockchain\$v2\$%d\$%s\$%s", $iterations, length ($salt . $encrypted) / 2, $salt . $encrypted);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my (undef, $signature, $version, $iterations, $data_len, $data) = split '\$', $hash;
|
||||
|
||||
return unless ($signature eq "blockchain");
|
||||
return unless ($version eq "v2");
|
||||
return unless (($data_len * 2) == length $data);
|
||||
|
||||
my $salt = substr ($data, 0, 32);
|
||||
my $encrypted = substr ($data, 32);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iterations, $encrypted);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user