diff --git a/docs/changes.txt b/docs/changes.txt index 2c1a213d9..ab4acacde 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -88,6 +88,7 @@ - Metal Backend: added workaround to prevent 'Infinite Loop' bug when build kernels - User Options: added --metal-compiler-runtime option - Help: show supported hash-modes only with -hh +- Unit tests: add test modules for hash-modes 31500 and 31600 and handle them in tools/test.pl * changes v6.2.5 -> v6.2.6 diff --git a/tools/test.pl b/tools/test.pl index 2ea8b094d..8d294d61c 100755 --- a/tools/test.pl +++ b/tools/test.pl @@ -13,6 +13,10 @@ use File::Basename; use FindBin; use List::Util 'shuffle'; +# used by hash-mode 31500 and 31600 +use Text::Iconv; +use Digest::MD4 qw (md4_hex); + # allows require by filename use lib "$FindBin::Bin/test_modules"; @@ -159,6 +163,13 @@ sub single { for my $salt (sort { length $a <=> length $b } keys %{$db_prev->{$word}}) { + if ($MODE == 31500 || $MODE == 31600) + { + my $converter = Text::Iconv->new('utf8', 'UTF-16LE'); + + $word = md4_hex ($converter->convert ($word)); + } + my $hash = module_generate_hash ($word, $salt); # possible if the requested length is not supported by algorithm @@ -229,6 +240,13 @@ sub passthrough $idx++; + if ($MODE == 31500 || $MODE == 31600) + { + my $converter = Text::Iconv->new('utf8', 'UTF-16LE'); + + $word = md4_hex ($converter->convert ($word)); + } + my $hash = module_generate_hash ($word, $salt); next unless defined $hash; diff --git a/tools/test_modules/m31500.pm b/tools/test_modules/m31500.pm new file mode 100644 index 000000000..d1efbf4c3 --- /dev/null +++ b/tools/test_modules/m31500.pm @@ -0,0 +1,49 @@ +#!/usr/bin/env perl + +## +## Author......: See docs/credits.txt +## License.....: MIT +## + +use strict; +use warnings; + +use Digest::MD4 qw (md4_hex); +use Encode; + +sub module_constraints { [[32, 32], [0, 256], [-1, -1], [-1, -1], [-1, -1]] } + +sub module_generate_hash +{ + my $word = shift; + my $salt = shift; + + my $word_bin = pack ("H*", $word); + + my $salt_bin = encode ("UTF-16LE", lc ($salt)); + + my $digest = md4_hex ($word_bin . $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; diff --git a/tools/test_modules/m31600.pm b/tools/test_modules/m31600.pm new file mode 100644 index 000000000..aa7fcf99d --- /dev/null +++ b/tools/test_modules/m31600.pm @@ -0,0 +1,76 @@ +#!/usr/bin/env perl + +## +## Author......: See docs/credits.txt +## License.....: MIT +## + +use strict; +use warnings; + +use Digest::MD4 qw (md4); +use Crypt::PBKDF2; +use Encode; + +sub module_constraints { [[32, 32], [0, 256], [-1, -1], [-1, -1], [-1, -1]] } + +sub module_generate_hash +{ + my $word = shift; + my $salt = shift; + my $iterations = shift // 10240; + + my $salt_bin = encode ("UTF-16LE", lc ($salt)); + + my $pbkdf2 = Crypt::PBKDF2->new + ( + hash_class => 'HMACSHA1', + iterations => $iterations, + output_len => 16, + salt_len => length ($salt_bin), + ); + + my $word_bin = pack ("H*", $word); + + my $digest = unpack ("H*", $pbkdf2->PBKDF2 ($salt_bin, md4 ($word_bin . $salt_bin))); + + my $hash = sprintf ("\$DCC2\$%i#%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 $signature = substr ($hash, 0, 6); + + return unless ($signature eq '$DCC2$'); + + $hash = substr ($hash, 6); + + my @data = split ('#', $hash); + + return unless scalar @data == 3; + + my $iterations = shift @data; + my $salt = shift @data; + my $digest = shift @data; + + return unless defined $iterations; + return unless defined $salt; + return unless defined $digest; + + my $word_packed = pack_if_HEX_notation ($word); + + my $new_hash = module_generate_hash ($word_packed, $salt, $iterations); + + return ($new_hash, $word); +} + +1;