mirror of
https://github.com/hashcat/hashcat.git
synced 2025-08-04 12:56:00 +00:00
157 lines
2.8 KiB
Perl
Executable File
157 lines
2.8 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
|
|
##
|
|
## Author......: See docs/credits.txt
|
|
## License.....: MIT
|
|
##
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Math::BigInt;
|
|
|
|
sub module_constraints { [[0, 256], [16, 16], [0, 63], [16, 16], [-1, -1]] }
|
|
|
|
my $u64_width = Math::BigInt->new("0x10000000000000000"); # 2**64
|
|
|
|
# Ensure that uint64 integer overflow is replicated correctly
|
|
sub wrapping_mul
|
|
{
|
|
my $a = shift;
|
|
my $b = shift;
|
|
|
|
return ($a * $b)->bmod($u64_width);
|
|
}
|
|
|
|
my $m = Math::BigInt->new("0xc6a4a7935bd1e995");
|
|
my $r = 47;
|
|
|
|
sub murmurhash64a
|
|
{
|
|
use integer;
|
|
|
|
my $word = shift;
|
|
my $seed = shift;
|
|
|
|
my @chars = unpack ("C*", $word);
|
|
my $len = length $word;
|
|
|
|
my $hash = $seed ^ wrapping_mul ($len, $m);
|
|
|
|
my $endpos = $len - ($len & 7);
|
|
my $i;
|
|
|
|
for ($i = 0; $i < $endpos; $i += 8)
|
|
{
|
|
my $c0 = $chars[$i + 0];
|
|
my $c1 = $chars[$i + 1];
|
|
my $c2 = $chars[$i + 2];
|
|
my $c3 = $chars[$i + 3];
|
|
my $c4 = $chars[$i + 4];
|
|
my $c5 = $chars[$i + 5];
|
|
my $c6 = $chars[$i + 6];
|
|
my $c7 = $chars[$i + 7];
|
|
|
|
my $k = ($c0 << 0)
|
|
| ($c1 << 8)
|
|
| ($c2 << 16)
|
|
| ($c3 << 24)
|
|
| ($c4 << 32)
|
|
| ($c5 << 40)
|
|
| ($c6 << 48)
|
|
| ($c7 << 56);
|
|
|
|
$k = wrapping_mul ($k, $m);
|
|
$k ^= $k >> $r;
|
|
$k = wrapping_mul ($k, $m);
|
|
|
|
$hash ^= $k;
|
|
$hash = wrapping_mul ($hash, $m);
|
|
}
|
|
|
|
my $overflow = $len & 7;
|
|
|
|
if ($overflow == 7)
|
|
{
|
|
$hash ^= $chars[$i + 6] << 48;
|
|
}
|
|
if ($overflow >= 6)
|
|
{
|
|
$hash ^= $chars[$i + 5] << 40;
|
|
}
|
|
if ($overflow >= 5)
|
|
{
|
|
$hash ^= $chars[$i + 4] << 32;
|
|
}
|
|
if ($overflow >= 4)
|
|
{
|
|
$hash ^= $chars[$i + 3] << 24;
|
|
}
|
|
if ($overflow >= 3)
|
|
{
|
|
$hash ^= $chars[$i + 2] << 16;
|
|
}
|
|
if ($overflow >= 2)
|
|
{
|
|
$hash ^= $chars[$i + 1] << 8;
|
|
}
|
|
if ($overflow >= 1)
|
|
{
|
|
$hash ^= $chars[$i + 0] << 0;
|
|
}
|
|
|
|
if ($overflow > 0)
|
|
{
|
|
$hash = wrapping_mul ($hash, $m);
|
|
}
|
|
|
|
$hash ^= $hash >> $r;
|
|
$hash = wrapping_mul ($hash, $m);
|
|
$hash ^= $hash >> $r;
|
|
|
|
return $hash;
|
|
}
|
|
|
|
sub module_generate_hash
|
|
{
|
|
my $word = shift;
|
|
my $salt = shift;
|
|
|
|
my $salt_bin = pack ("H*", $salt);
|
|
|
|
my $seed = unpack ("Q>", $salt_bin);
|
|
|
|
my $digest = murmurhash64a ($word, $seed);
|
|
|
|
$digest = unpack ("H*", pack ("Q>", $digest));
|
|
|
|
my $hash = sprintf ("%s:%016x", $digest, $seed);
|
|
|
|
return $hash;
|
|
}
|
|
|
|
sub module_verify_hash
|
|
{
|
|
my $line = shift;
|
|
|
|
my ($hash, $seed, $word) = split (':', $line, 3);
|
|
|
|
return unless defined $hash;
|
|
return unless defined $seed;
|
|
return unless defined $word;
|
|
|
|
return unless length $hash == 16;
|
|
return unless length $seed == 16;
|
|
|
|
return unless ($hash =~ m/^[0-9a-fA-F]{16}$/);
|
|
return unless ($seed =~ m/^[0-9a-fA-F]{16}$/);
|
|
|
|
my $word_packed = pack_if_HEX_notation ($word);
|
|
my $seed_packed = pack_if_HEX_notation ($seed);
|
|
|
|
my $new_hash = module_generate_hash ($word_packed, $seed_packed);
|
|
|
|
return ($new_hash, $word);
|
|
}
|
|
|
|
1;
|