Merge branch 'master' into new-3500-mode
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::MD5 qw (md5_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [2, 2], [0, 55], [2, 2], [2, 55]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = md5_hex ($salt . $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;
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::MD5 qw (md5_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = md5_hex (encode ("UTF-16LE", $word));
|
||||
|
||||
my $hash = sprintf ("%s", $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
$word = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA1 qw (sha1_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha1_hex (encode ("UTF-16LE", $word));
|
||||
|
||||
my $hash = sprintf ("%s", $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
$word = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -9,7 +9,7 @@ use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::MD4 qw (md4_hex);
|
||||
use Encode;
|
||||
use Text::Iconv;
|
||||
|
||||
sub module_constraints { [[0, 256], [-1, -1], [0, 27], [-1, -1], [-1, -1]] }
|
||||
|
||||
@@ -17,7 +17,9 @@ sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = md4_hex (encode ('UTF-16LE', $word));
|
||||
my $converter = Text::Iconv->new('utf8', 'UTF-16LE');
|
||||
|
||||
my $digest = md4_hex ($converter->convert ($word));
|
||||
|
||||
return $digest;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/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, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = sha256_hex (encode ("UTF-16LE", $word));
|
||||
|
||||
my $hash = sprintf ("%s", $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha512_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = sha512_hex (encode ("UTF-16LE", $word));
|
||||
|
||||
my $hash = sprintf ("%s", $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -10,7 +10,7 @@ use warnings;
|
||||
|
||||
use Authen::Passphrase::LANManager;
|
||||
|
||||
sub module_constraints { [[0, 7], [-1, -1], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
sub module_constraints { [[1, 7], [-1, -1], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/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, 256], [0, 127], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha1_hex (sha1_hex ($salt . $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;
|
||||
@@ -17,8 +17,8 @@ sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $N = shift // 1024;
|
||||
my $r = shift // 1;
|
||||
my $N = shift // 16384;
|
||||
my $r = shift // 8;
|
||||
my $p = shift // 1;
|
||||
|
||||
my $hash_buf = scrypt_hash ($word, $salt, $N, $r, $p, 32);
|
||||
|
||||
@@ -48,7 +48,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 16,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $cipher2 = Crypt::CBC->new ({
|
||||
@@ -58,7 +58,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 16,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $encdata;
|
||||
|
||||
@@ -48,7 +48,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $cipher2 = Crypt::CBC->new ({
|
||||
@@ -58,7 +58,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $encdata;
|
||||
|
||||
@@ -65,7 +65,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 16,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $data = $aes->encrypt ($data);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha384_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 55], [0, 55], [0, 55]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha384_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;
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha384_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 55], [0, 55], [0, 55]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha384_hex ($salt . $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;
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha384_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha384_hex (encode ("UTF-16LE", $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;
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha384_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha384_hex ($salt . encode ("UTF-16LE", $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;
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA qw (sha384_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = sha384_hex (encode ("UTF-16LE", $word));
|
||||
|
||||
my $hash = sprintf ("%s", $digest);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -12,7 +12,7 @@ use Digest::SHA;
|
||||
use Crypt::CBC;
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 127], [8, 8], [0, 20], [8, 8], [-1, -1]] }
|
||||
sub module_constraints { [[0, 128], [8, 8], [0, 20], [8, 8], [-1, -1]] }
|
||||
|
||||
my $ITERATIONS = 0x40000;
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p2 = Crypt::ECB->new ({
|
||||
@@ -199,7 +199,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p3 = Crypt::ECB->new ({
|
||||
@@ -208,7 +208,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
# let's compute a 3DES-EDE-CBC decryption
|
||||
@@ -256,7 +256,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $expected_cleartext = $aes->decrypt ($cipher);
|
||||
@@ -288,7 +288,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p2 = Crypt::ECB->new ({
|
||||
@@ -297,7 +297,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p3 = Crypt::ECB->new ({
|
||||
@@ -306,7 +306,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
# let's compute a 3DES-EDE-CBC encryption
|
||||
@@ -342,7 +342,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
$cipher = $aes->encrypt ($cleartext);
|
||||
|
||||
@@ -192,7 +192,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p2 = Crypt::ECB->new ({
|
||||
@@ -201,7 +201,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p3 = Crypt::ECB->new ({
|
||||
@@ -210,7 +210,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
# let's compute a 3DES-EDE-CBC decryption
|
||||
@@ -258,7 +258,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $expected_cleartext = $aes->decrypt ($cipher);
|
||||
@@ -290,7 +290,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p2 = Crypt::ECB->new ({
|
||||
@@ -299,7 +299,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $p3 = Crypt::ECB->new ({
|
||||
@@ -308,7 +308,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 8,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
# let's compute a 3DES-EDE-CBC encryption
|
||||
@@ -344,7 +344,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
$cipher = $aes->encrypt ($cleartext);
|
||||
|
||||
@@ -33,7 +33,7 @@ sub module_generate_hash
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
keysize => 32,
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
if (defined $plain_bin)
|
||||
|
||||
@@ -10,7 +10,7 @@ use warnings;
|
||||
|
||||
use Digest::SHA qw (sha256_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 55], [16, 16], [-1, -1]] }
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 55], [0, 51], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64 qw (encode_base64 decode_base64);
|
||||
use Crypt::PBKDF2;
|
||||
use Digest::SHA qw (sha512);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hash_class => 'HMACSHA1',
|
||||
iterations => 1000,
|
||||
output_len => 1024
|
||||
);
|
||||
|
||||
my $salt_b64 = encode_base64 ($salt, "");
|
||||
|
||||
my $key = $kdf->PBKDF2 ($salt, $word);
|
||||
|
||||
my $key_b64 = encode_base64 (sha512 ($key), "");
|
||||
|
||||
my $hash = sprintf ("\$solarwinds\$1\$%s\$%s", $salt_b64, $key_b64);
|
||||
|
||||
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;
|
||||
my $sig_dec = shift @data;
|
||||
my $salt = shift @data;
|
||||
my $digest = shift @data;
|
||||
|
||||
return unless ($signature eq "solarwinds");
|
||||
return unless ($sig_dec eq "1");
|
||||
|
||||
return unless length ($salt) == 24;
|
||||
return unless length ($digest) == 88;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -12,7 +12,7 @@ use Digest::SHA qw (sha256);
|
||||
use Digest::HMAC qw (hmac_hex);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
sub module_constraints { [[0, 128], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ sub module_generate_hash
|
||||
cipher => "DES",
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $des2 = Crypt::CBC->new ({
|
||||
@@ -53,7 +53,7 @@ sub module_generate_hash
|
||||
cipher => "DES",
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $des3 = Crypt::CBC->new ({
|
||||
@@ -62,7 +62,7 @@ sub module_generate_hash
|
||||
cipher => "DES",
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "null",
|
||||
padding => "none",
|
||||
});
|
||||
|
||||
my $data_encrypted = "";
|
||||
|
||||
@@ -75,7 +75,7 @@ sub module_generate_hash
|
||||
keysize => 16,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "null"
|
||||
padding => "none"
|
||||
});
|
||||
|
||||
if ($is_decrypt == 1)
|
||||
|
||||
@@ -13,7 +13,7 @@ use Crypt::CBC;
|
||||
use Encode;
|
||||
use Digest::CRC qw (crc32);
|
||||
|
||||
sub module_constraints { [[0, 127], [8, 8], [0, 20], [8, 8], [-1, -1]] }
|
||||
sub module_constraints { [[0, 128], [8, 8], [0, 20], [8, 8], [-1, -1]] }
|
||||
|
||||
my $ITERATIONS = 0x40000;
|
||||
|
||||
@@ -375,7 +375,7 @@ sub module_generate_hash
|
||||
-keysize => 16,
|
||||
-literal_key => 1,
|
||||
-header => 'none',
|
||||
-padding => 'null'
|
||||
-padding => 'none'
|
||||
);
|
||||
|
||||
if (defined ($data))
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64 qw (decode_base64 encode_base64);
|
||||
use Digest::MD5 qw (md5_hex);
|
||||
use Digest::SHA1 qw (sha1);
|
||||
use Digest::HMAC qw (hmac);
|
||||
use Crypt::PBKDF2;
|
||||
|
||||
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
my $ITERATIONS = 10000;
|
||||
my $MD5_SALT = ":mongo:";
|
||||
my $HMAC_SALT = "Server Key";
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift // $ITERATIONS;
|
||||
my $user = shift // random_string (random_number (0, 57));
|
||||
|
||||
my $pbkdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hash_class => 'HMACSHA1',
|
||||
iterations => $iter,
|
||||
output_len => 20
|
||||
);
|
||||
|
||||
my $md5_dgst = md5_hex ($user . $MD5_SALT . $word);
|
||||
|
||||
my $pbkdf2_dgst = $pbkdf->PBKDF2 ($salt, $md5_dgst);
|
||||
|
||||
my $hash_buf = hmac ($HMAC_SALT, $pbkdf2_dgst, \&sha1);
|
||||
|
||||
my $hash = sprintf ('$mongodb-scram$*0*%s*%i*%s*%s', encode_base64 ($user, ""), $iter, encode_base64 ($salt, ""), encode_base64 ($hash_buf, ""));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return unless $idx >= 0;
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 17) eq '$mongodb-scram$*0';
|
||||
|
||||
my (undef, undef, $user, $iter, $salt) = split ('\*', $hash);
|
||||
|
||||
return unless defined ($user);
|
||||
return unless defined ($iter);
|
||||
return unless defined ($salt);
|
||||
|
||||
return unless ($user =~ m/^[A-Za-z0-9+\/=]{0,76}$/);
|
||||
|
||||
$user = decode_base64 ($user);
|
||||
|
||||
return unless (length ($user) <= 57);
|
||||
|
||||
return unless ($iter =~ m/^[1-9][0-9]{0,7}$/);
|
||||
|
||||
$iter = int ($iter);
|
||||
|
||||
return unless ($salt =~ m/^[A-Za-z0-9+\/=]{24}$/);
|
||||
|
||||
$salt = decode_base64 ($salt);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iter, $user);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64 qw (decode_base64 encode_base64);
|
||||
use Digest::SHA qw (sha256);
|
||||
use Digest::HMAC qw (hmac);
|
||||
use Crypt::PBKDF2;
|
||||
|
||||
sub module_constraints { [[0, 256], [28, 28], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
my $ITERATIONS = 15000;
|
||||
my $HMAC_SALT = "Server Key";
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift // $ITERATIONS;
|
||||
my $user = shift // random_string (random_number (0, 64));
|
||||
|
||||
my $pbkdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256),
|
||||
iterations => $iter,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
my $pbkdf2_dgst = $pbkdf->PBKDF2 ($salt, $word);
|
||||
|
||||
my $hash_buf = hmac ($HMAC_SALT, $pbkdf2_dgst, \&sha256);
|
||||
|
||||
my $hash = sprintf ('$mongodb-scram$*1*%s*%i*%s*%s', encode_base64 ($user, ""), $iter, encode_base64 ($salt, ""), encode_base64 ($hash_buf, ""));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return unless $idx >= 0;
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 17) eq '$mongodb-scram$*1';
|
||||
|
||||
my (undef, undef, $user, $iter, $salt) = split ('\*', $hash);
|
||||
|
||||
return unless defined ($user);
|
||||
return unless defined ($iter);
|
||||
return unless defined ($salt);
|
||||
|
||||
return unless ($user =~ m/^[A-Za-z0-9+\/=]{0,88}$/);
|
||||
|
||||
$user = decode_base64 ($user);
|
||||
|
||||
return unless (length ($user) <= 64);
|
||||
|
||||
return unless ($iter =~ m/^[1-9][0-9]{0,7}$/);
|
||||
|
||||
$iter = int ($iter);
|
||||
|
||||
return unless ($salt =~ m/^[A-Za-z0-9+\/=]{40}$/);
|
||||
|
||||
$salt = decode_base64 ($salt);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iter, $user);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/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, 256], [0, 256], [0, 55], [0, 31], [0, 55]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $digest = sha1_hex ($salt . sha1_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;
|
||||
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Digest::SHA qw (sha1 sha512);
|
||||
use Crypt::Mode::ECB;
|
||||
|
||||
sub module_constraints { [[0, 256], [32, 32], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
my $AES256_IGE_BLOCK_SIZE = 16;
|
||||
|
||||
#
|
||||
# Helper functions:
|
||||
#
|
||||
|
||||
sub exclusive_or
|
||||
{
|
||||
my $in1 = shift;
|
||||
my $in2 = shift;
|
||||
|
||||
# MIN () function (should always be 16 for us):
|
||||
# my $len = (length ($in1) <= length ($in2)) ? length ($in2) : length ($in1);
|
||||
|
||||
# padding if input not multiple of block size:
|
||||
# $in1 .= "\x00" x ($AES256_IGE_BLOCK_SIZE - $len);
|
||||
# $in2 .= "\x00" x ($AES256_IGE_BLOCK_SIZE - $len);
|
||||
|
||||
my $out = "";
|
||||
|
||||
for (my $i = 0; $i < $AES256_IGE_BLOCK_SIZE; $i++) # $i < $len
|
||||
{
|
||||
$out .= chr (ord (substr ($in1, $i, 1)) ^ ord (substr ($in2, $i, 1)));
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub aes256_encrypt_ige
|
||||
{
|
||||
my $key = shift;
|
||||
my $iv = shift;
|
||||
my $in = shift;
|
||||
|
||||
my $x_prev = substr ($iv, $AES256_IGE_BLOCK_SIZE, $AES256_IGE_BLOCK_SIZE);
|
||||
my $y_prev = substr ($iv, 0, $AES256_IGE_BLOCK_SIZE);
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
my $out = "";
|
||||
|
||||
for (my $i = 0; $i < length ($in); $i += $AES256_IGE_BLOCK_SIZE)
|
||||
{
|
||||
my $x = substr ($in, $i, $AES256_IGE_BLOCK_SIZE);
|
||||
|
||||
my $y_xor = exclusive_or ($x, $y_prev);
|
||||
|
||||
my $y_final = $m->encrypt ($y_xor, $key);
|
||||
# $y_final .= "\x00" x ($AES256_IGE_BLOCK_SIZE - length ($y_final));
|
||||
|
||||
my $y = exclusive_or ($y_final, $x_prev);
|
||||
|
||||
$x_prev = $x;
|
||||
$y_prev = $y;
|
||||
|
||||
$out .= $y;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub aes256_decrypt_ige
|
||||
{
|
||||
my $key = shift;
|
||||
my $iv = shift;
|
||||
my $in = shift;
|
||||
|
||||
my $x_prev = substr ($iv, 0, $AES256_IGE_BLOCK_SIZE);
|
||||
my $y_prev = substr ($iv, $AES256_IGE_BLOCK_SIZE, $AES256_IGE_BLOCK_SIZE);
|
||||
|
||||
my $m = Crypt::Mode::ECB->new ('AES', 0);
|
||||
|
||||
my $out = "";
|
||||
|
||||
for (my $i = 0; $i < length ($in); $i += $AES256_IGE_BLOCK_SIZE)
|
||||
{
|
||||
my $x = substr ($in, $i, $AES256_IGE_BLOCK_SIZE);
|
||||
|
||||
my $y_xor = exclusive_or ($x, $y_prev);
|
||||
|
||||
my $y_final = $m->decrypt ($y_xor, $key);
|
||||
# $y_final .= "\x00" x ($AES256_IGE_BLOCK_SIZE - length ($y_final));
|
||||
|
||||
my $y = exclusive_or ($y_final, $x_prev);
|
||||
|
||||
$x_prev = $x;
|
||||
$y_prev = $y;
|
||||
|
||||
$out .= $y;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift // 100000;
|
||||
my $data = shift;
|
||||
|
||||
my $sha512_hash = sha512 ($salt . $word . $salt);
|
||||
|
||||
my $pbkdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512),
|
||||
iterations => $iter,
|
||||
output_len => 136
|
||||
);
|
||||
|
||||
my $authkey = $pbkdf->PBKDF2 ($salt, $sha512_hash);
|
||||
|
||||
my $message = "";
|
||||
my $message_key = "";
|
||||
|
||||
if (defined ($data))
|
||||
{
|
||||
$message = substr ($data, 16);
|
||||
$message_key = substr ($data, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = random_bytes (272);
|
||||
$message_key = substr (sha1 ($message), 0, 16);
|
||||
}
|
||||
|
||||
my $data_a = "\x00" x 48;
|
||||
my $data_b = "\x00" x 48;
|
||||
my $data_c = "\x00" x 48;
|
||||
my $data_d = "\x00" x 48;
|
||||
|
||||
substr ($data_a, 0, 16) = $message_key; # memcpy ()
|
||||
substr ($data_b, 16, 16) = $message_key;
|
||||
substr ($data_c, 32, 16) = $message_key;
|
||||
substr ($data_d, 0, 16) = $message_key;
|
||||
|
||||
substr ($data_a, 16, 32) = substr ($authkey, 8, 32);
|
||||
substr ($data_b, 0, 16) = substr ($authkey, 40, 16);
|
||||
substr ($data_b, 32, 16) = substr ($authkey, 56, 16);
|
||||
substr ($data_c, 0, 32) = substr ($authkey, 72, 32);
|
||||
substr ($data_d, 16, 32) = substr ($authkey, 104, 32);
|
||||
|
||||
my $sha1_a = sha1 ($data_a);
|
||||
my $sha1_b = sha1 ($data_b);
|
||||
my $sha1_c = sha1 ($data_c);
|
||||
my $sha1_d = sha1 ($data_d);
|
||||
|
||||
my $aes_key = substr ($sha1_a, 0, 8) . # 8 +
|
||||
substr ($sha1_b, 8, 12) . # 12 +
|
||||
substr ($sha1_c, 4, 12); # 12 = 32
|
||||
|
||||
my $aes_iv = substr ($sha1_a, 8, 12) . # 12 +
|
||||
substr ($sha1_b, 0, 8) . # 8 +
|
||||
substr ($sha1_c, 16, 4) . # 4 +
|
||||
substr ($sha1_d, 0, 8); # 8 = 32
|
||||
|
||||
my $enc_data = "";
|
||||
|
||||
if (defined ($data))
|
||||
{
|
||||
# AES256 IGE decrypt:
|
||||
|
||||
my $dec_data = aes256_decrypt_ige ($aes_key, $aes_iv, $message);
|
||||
|
||||
my $h = substr (sha1 ($dec_data), 0, 16);
|
||||
|
||||
if ($h eq $message_key)
|
||||
{
|
||||
$enc_data = $data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# AES256 IGE encrypt:
|
||||
|
||||
my $enc_random_data = aes256_encrypt_ige ($aes_key, $aes_iv, $message);
|
||||
|
||||
$enc_data = $message_key . $enc_random_data;
|
||||
}
|
||||
|
||||
my $hash = sprintf ("\$telegram\$2*%i*%s*%s", $iter, unpack ("H*", $salt), unpack ("H*", $enc_data));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return if ($idx == -1);
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $signature = substr ($hash, 0, 10);
|
||||
|
||||
return unless ($signature eq "\$telegram\$");
|
||||
|
||||
my $version = substr ($hash, 10, 1);
|
||||
|
||||
return unless ($version eq "2");
|
||||
|
||||
my @split = split ('\*', $hash);
|
||||
|
||||
return unless (scalar (@split) == 4);
|
||||
|
||||
shift (@split);
|
||||
|
||||
my $iter = shift (@split);
|
||||
my $salt = shift (@split);
|
||||
my $data = shift (@split);
|
||||
|
||||
return unless length ($salt) == 64;
|
||||
return unless length ($data) == 576;
|
||||
|
||||
return unless ($iter =~ /^[1-9][0-9]*$/);
|
||||
|
||||
return unless ($salt =~ /^[0-9a-fA-F]*$/);
|
||||
return unless ($data =~ /^[0-9a-fA-F]*$/);
|
||||
|
||||
$salt = pack ("H*", $salt);
|
||||
$data = pack ("H*", $data);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iter, $data);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/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, 256], [32, 32], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $type = shift // 1; #random_number (1, 3);
|
||||
my $iter = shift // random_number (10000, 20000);
|
||||
my $iv = shift // random_hex_string (32);
|
||||
my $enc = shift;
|
||||
|
||||
my $kdf;
|
||||
|
||||
if ($type == 1)
|
||||
{
|
||||
$kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hash_class => 'HMACSHA1',
|
||||
iterations => $iter,
|
||||
output_len => 32
|
||||
);
|
||||
}
|
||||
elsif ($type == 2)
|
||||
{
|
||||
$kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256),
|
||||
iterations => $iter,
|
||||
output_len => 32
|
||||
);
|
||||
}
|
||||
elsif ($type == 3)
|
||||
{
|
||||
$kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512),
|
||||
iterations => $iter,
|
||||
output_len => 32
|
||||
);
|
||||
}
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $key = $kdf->PBKDF2 ($salt_bin, $word);
|
||||
|
||||
my $iv_bin = pack ("H*", $iv);
|
||||
|
||||
my $data;
|
||||
|
||||
if (defined $enc)
|
||||
{
|
||||
my $aes_cbc = Crypt::CBC->new ({
|
||||
cipher => "Crypt::Rijndael",
|
||||
iv => $iv_bin,
|
||||
key => $key,
|
||||
keysize => 32,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "none"
|
||||
});
|
||||
|
||||
my $enc_bin = pack ("H*", $enc);
|
||||
|
||||
$data = $aes_cbc->decrypt ($enc_bin);
|
||||
|
||||
if (substr ($data, 0, 12) ne "\x00" x 12)
|
||||
{
|
||||
$data = "\xff" x 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = "\x00" x 16;
|
||||
}
|
||||
|
||||
my $aes_cbc = Crypt::CBC->new ({
|
||||
cipher => "Crypt::Rijndael",
|
||||
iv => $iv_bin,
|
||||
key => $key,
|
||||
keysize => 32,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "none"
|
||||
});
|
||||
|
||||
my $enc_bin = $aes_cbc->encrypt ($data);
|
||||
|
||||
my $hash = sprintf ("SQLCIPHER*%d*%d*%s*%s*%s", $type, $iter, unpack ("H*", $salt_bin), unpack ("H*", $iv_bin), unpack ("H*", $enc_bin));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return unless $idx >= 0;
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 9) eq 'SQLCIPHER';
|
||||
|
||||
my ($signature, $type, $iter, $salt, $iv, $data) = split '\*', $hash;
|
||||
|
||||
return unless defined $signature;
|
||||
return unless defined $type;
|
||||
return unless defined $iter;
|
||||
return unless defined $salt;
|
||||
return unless defined $iv;
|
||||
return unless defined $data;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $type, $iter, $iv, $data);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::MD5 qw (md5_hex);
|
||||
use Digest::MD5 qw (md5);
|
||||
|
||||
sub module_constraints { [[0, 256], [-1, -1], [0, 55], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest1 = md5 ($word);
|
||||
|
||||
my $digest1_sub = substr ($digest1, 0, 5);
|
||||
|
||||
my $digest2 = md5 ($digest1_sub);
|
||||
|
||||
my $digest2_sub = substr ($digest2, 0, 5);
|
||||
|
||||
my $hash = sprintf ("%s", unpack ("H*", $digest2_sub));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA1 qw (sha1);
|
||||
use Digest::HMAC qw (hmac hmac_hex);
|
||||
use Encode qw (encode decode);
|
||||
use MIME::Base64;
|
||||
|
||||
sub module_constraints { [[0, 256], [0, 256], [0, 27], [0, 27], [0, 27]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $unicode_word = encode ("UTF-16LE", $word);
|
||||
|
||||
my $digest = hmac ($unicode_word, $unicode_word, \&sha1, 64);
|
||||
|
||||
my $hash = sprintf ("%s", encode_base64 ($digest, ""));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use MIME::Base64 qw (encode_base64 decode_base64);
|
||||
|
||||
use Digest::MD5 qw (md5);
|
||||
|
||||
sub module_constraints { [[-1, -1], [-1, -1], [0, 55], [-1, -1], [-1, -1]] }
|
||||
|
||||
my $itoa62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
my $digest = md5 ($word);
|
||||
|
||||
my @chksum;
|
||||
|
||||
for (my $i = 0, my $j = 0; $i < 16; $i += 2, $j += 1)
|
||||
{
|
||||
$chksum[$j] = (ord (substr ($digest, $i + 0, 1)) + ord (substr ($digest, $i + 1, 1))) % 62;
|
||||
|
||||
$chksum[$j] = substr ($itoa62, $chksum[$j], 1);
|
||||
}
|
||||
|
||||
my $res = join "", @chksum;
|
||||
|
||||
my $hash = sprintf ("%s", $res);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64 qw (encode_base64 decode_base64);
|
||||
use Digest::SHA qw (sha512);
|
||||
use Encode;
|
||||
|
||||
sub module_constraints { [[0, 64], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift // 100000;
|
||||
|
||||
my $tmp = sha512 ($salt . encode ("UTF-16LE", $word));
|
||||
|
||||
for (my $i = 0; $i < $iter; $i++)
|
||||
{
|
||||
my $num32 = pack ("L", $i);
|
||||
|
||||
$tmp = sha512 ($tmp . $num32);
|
||||
}
|
||||
|
||||
my $salt_b64 = encode_base64 ($salt, "");
|
||||
my $digest_b64 = encode_base64 ($tmp, "");
|
||||
|
||||
my $hash = sprintf ("\$office\$%d\$0\$%d\$%s\$%s", 2016, $iter, $salt_b64, $digest_b64);
|
||||
|
||||
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 == 7;
|
||||
return unless (shift @data eq 'office');
|
||||
return unless (shift @data eq '2016');
|
||||
return unless (shift @data eq '0');
|
||||
|
||||
my $iter = shift @data;
|
||||
my $salt = shift @data;
|
||||
my $digest = shift @data;
|
||||
|
||||
return unless defined $iter;
|
||||
return unless defined $salt;
|
||||
return unless defined $digest;
|
||||
|
||||
return unless length ($salt) == 24;
|
||||
return unless length ($digest) == 88;
|
||||
|
||||
my $new_hash = module_generate_hash ($word, $salt, $iter);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,277 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
# based off m10500 but added the owner password part ($o) to be able to test the edit password
|
||||
# two TODOs still (now only works if no user password is set):
|
||||
# 1. TODO use user password as input for md5 of o_digest if no owner password is set
|
||||
# 2. TODO dynamically add user password including padding to the RC4 input for the computation of the pdf o-value
|
||||
|
||||
# easy test shortcut for debugging
|
||||
# a=$(echo 1 | tools/test.pl passthrough 10500 | tail -n1); echo $a; echo 1 | ./hashcat --potfile-disable --runtime 400 --hwmon-disable -O -D 2 --backend-vector-width 4 -a 0 -m 10500 $a
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::RC4;
|
||||
use Digest::MD5 qw (md5);
|
||||
|
||||
my $PDF_PADDING =
|
||||
[
|
||||
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56,
|
||||
0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
|
||||
0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
|
||||
];
|
||||
|
||||
sub module_constraints { [[0, 15], [32, 32], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub pdf_compute_encryption_key_user
|
||||
{
|
||||
my $word = shift;
|
||||
my $padding = shift;
|
||||
my $id = shift;
|
||||
my $u = shift;
|
||||
my $o = shift;
|
||||
my $P = shift;
|
||||
my $V = shift;
|
||||
my $R = shift;
|
||||
my $enc = shift;
|
||||
|
||||
## start
|
||||
|
||||
my $data;
|
||||
|
||||
$data .= $word;
|
||||
|
||||
$data .= substr ($padding, 0, 32 - length $word);
|
||||
|
||||
$data .= pack ("H*", $o);
|
||||
$data .= pack ("I", $P);
|
||||
$data .= pack ("H*", $id);
|
||||
|
||||
if ($R >= 4)
|
||||
{
|
||||
if (!$enc)
|
||||
{
|
||||
$data .= pack ("I", -1);
|
||||
}
|
||||
}
|
||||
|
||||
my $res = md5 ($data);
|
||||
|
||||
if ($R >= 3)
|
||||
{
|
||||
for (my $i = 0; $i < 50; $i++)
|
||||
{
|
||||
$res = md5 ($res);
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
sub pdf_compute_encryption_key_owner
|
||||
{
|
||||
my $word = shift;
|
||||
my $padding = shift;
|
||||
my $id = shift;
|
||||
my $u = shift;
|
||||
my $o = shift;
|
||||
my $P = shift;
|
||||
my $V = shift;
|
||||
my $R = shift;
|
||||
my $enc = shift;
|
||||
|
||||
# TODO use user password as input for md5 of o_digest if no owner password is set
|
||||
my $data;
|
||||
$data .= $word;
|
||||
$data .= substr ($padding, 0, 32 - length $word);
|
||||
my $o_digest = md5 ($data);
|
||||
|
||||
if ($R >= 3)
|
||||
{
|
||||
for (my $i = 0; $i < 50; $i++)
|
||||
{
|
||||
$o_digest = md5 ($o_digest);
|
||||
}
|
||||
}
|
||||
|
||||
#printf("\$o_digest = %s\n", unpack ("H*", $o_digest));
|
||||
|
||||
|
||||
my $o_key;
|
||||
if ($R == 2)
|
||||
{
|
||||
$o_key = substr($o_digest, 0, 8); # rc4 key is always 5 for revision 2, but for 3 or greather is dependent on the value of the encryption dictionaries length entry
|
||||
}
|
||||
else
|
||||
{
|
||||
$o_key = substr($o_digest, 0, 16); #length is always 128 bits or 16 bytes
|
||||
}
|
||||
#printf("\$o_key = %s\n", unpack ("H*", $o_key));
|
||||
|
||||
return $o_key;
|
||||
}
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $id = shift;
|
||||
my $u = shift;
|
||||
my $o = shift;
|
||||
my $P = shift;
|
||||
my $V = shift;
|
||||
my $R = shift;
|
||||
my $enc = shift;
|
||||
|
||||
if (defined $u == 0)
|
||||
{
|
||||
$u = "0" x 64;
|
||||
}
|
||||
|
||||
my $u_save = $u;
|
||||
|
||||
if (defined $o == 0)
|
||||
{
|
||||
$o = "0" x 64;
|
||||
}
|
||||
|
||||
my $o_save = $u;
|
||||
|
||||
if (defined $R == 0)
|
||||
{
|
||||
$R = random_number (3, 4);
|
||||
}
|
||||
|
||||
if (defined $V == 0)
|
||||
{
|
||||
$V = ($R == 3) ? 2 : 4;
|
||||
}
|
||||
|
||||
if (defined $P == 0)
|
||||
{
|
||||
$P = ($R == 3) ? -4 : -1028;
|
||||
}
|
||||
|
||||
if (defined $enc == 0)
|
||||
{
|
||||
$enc = ($R == 3) ? 1 : random_number (0, 1);
|
||||
}
|
||||
|
||||
my $padding;
|
||||
|
||||
for (my $i = 0; $i < 32; $i++)
|
||||
{
|
||||
$padding .= pack ("C", $PDF_PADDING->[$i]);
|
||||
}
|
||||
|
||||
|
||||
################ USER PASSWORD #################
|
||||
my $res = pdf_compute_encryption_key_user($word, $padding, $id, $u, $o, $P, $V, $R, $enc);
|
||||
|
||||
my $digest = md5 ($padding . pack ("H*", $id));
|
||||
|
||||
my $m = Crypt::RC4->new ($res);
|
||||
$u = $m->RC4 ($digest);
|
||||
|
||||
my @ress = split "", $res;
|
||||
|
||||
#do xor of rc4 19 times
|
||||
for (my $x = 1; $x <= 19; $x++)
|
||||
{
|
||||
my @xor;
|
||||
|
||||
for (my $i = 0; $i < 16; $i++)
|
||||
{
|
||||
$xor[$i] = chr (ord ($ress[$i]) ^ $x);
|
||||
}
|
||||
|
||||
my $s = join ("", @xor);
|
||||
|
||||
my $m2 = Crypt::RC4->new ($s);
|
||||
|
||||
$u = $m2->RC4 ($u);
|
||||
}
|
||||
|
||||
|
||||
################ OWNER PASSWORD #################
|
||||
my $o_key = pdf_compute_encryption_key_owner($word, $padding, $id, $u, $o, $P, $V, $R, $enc);
|
||||
my $n = Crypt::RC4->new ($o_key);
|
||||
$o = $n->RC4(substr ($padding, 0, 32 - length "")); # TODO dynamically add user password including padding to the RC4 input for the computation of the pdf o-value
|
||||
|
||||
#printf("padding_empty_str = %s\n", unpack ("H*", substr ($padding, 0, 32 - length "")));
|
||||
|
||||
my @ress2 = split "", $o_key;
|
||||
|
||||
if ($R >= 3)
|
||||
{
|
||||
#do xor of rc4 19 times
|
||||
for (my $x = 1; $x <= 19; $x++)
|
||||
{
|
||||
my @xor;
|
||||
|
||||
for (my $i = 0; $i < 16; $i++)
|
||||
{
|
||||
$xor[$i] = chr (ord ($ress2[$i]) ^ $x);
|
||||
}
|
||||
|
||||
my $s = join ("", @xor);
|
||||
|
||||
my $n2 = Crypt::RC4->new ($s);
|
||||
|
||||
$o = $n2->RC4 ($o);
|
||||
}
|
||||
}
|
||||
|
||||
#printf("\$u = %s\n", unpack ("H*", $u));
|
||||
|
||||
$u .= substr (pack ("H*", $u_save), 16, 16);
|
||||
|
||||
#printf("\$o = %s\n", unpack ("H*", $o));
|
||||
#printf("\$u = %s\n", unpack ("H*", $u));
|
||||
|
||||
my $hash = sprintf ('$pdf$%d*%d*128*%d*%d*16*%s*32*%s*32*%s', $V, $R, $P, $enc, $id, unpack ("H*", $u), unpack ("H*", $o));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash_in, $word) = split ":", $line;
|
||||
|
||||
return unless defined $hash_in;
|
||||
return unless defined $word;
|
||||
|
||||
my @data = split /\*/, $hash_in;
|
||||
|
||||
return unless scalar @data == 11;
|
||||
|
||||
my $V = shift @data; $V = substr ($V, 5, 1);
|
||||
my $R = shift @data;
|
||||
return unless (shift @data eq '128'); # length is always 128 here
|
||||
my $P = shift @data;
|
||||
my $enc = shift @data;
|
||||
return unless (shift @data eq '16');
|
||||
my $id = shift @data;
|
||||
return unless (shift @data eq '32');
|
||||
my $u = shift @data;
|
||||
return unless (shift @data eq '32');
|
||||
my $o = shift @data;
|
||||
|
||||
return unless defined $id;
|
||||
return unless defined $word;
|
||||
|
||||
$word = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word, $id, $u, $o, $P, $V, $R, $enc);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::Eksblowfish::Bcrypt qw (bcrypt en_base64);
|
||||
use MIME::Base64 qw (decode_base64);
|
||||
use Digest::MD5 qw (md5_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift;
|
||||
|
||||
my $cost = "05";
|
||||
|
||||
if (length ($iter))
|
||||
{
|
||||
$cost = $iter;
|
||||
}
|
||||
|
||||
my $md5_word = md5_hex ($word);
|
||||
|
||||
my $hash = bcrypt ($md5_word, sprintf ('$2a$%s$%s$', $cost, en_base64 ($salt)));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $index1 = index ($line, ":", 33);
|
||||
|
||||
return if $index1 < 1;
|
||||
|
||||
my $hash = substr ($line, 0, $index1);
|
||||
my $word = substr ($line, $index1 + 1);
|
||||
|
||||
my $index2 = index ($hash, "\$", 4);
|
||||
|
||||
my $iter = substr ($hash, 4, $index2 - 4);
|
||||
|
||||
my $plain_base64 = substr ($hash, $index2 + 1, 22);
|
||||
|
||||
# base64 mapping
|
||||
|
||||
my $base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
my $itoa64_2 = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
my $encoded = "";
|
||||
|
||||
for (my $i = 0; $i < length ($plain_base64); $i++)
|
||||
{
|
||||
my $char = substr ($plain_base64, $i, 1);
|
||||
|
||||
$encoded .= substr ($base64, index ($itoa64_2, $char), 1);
|
||||
}
|
||||
|
||||
my $salt = decode_base64 ($encoded);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iter);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub module_constraints { [[0, 256], [8, 8], [0, 55], [8, 8], [-1, -1]] }
|
||||
|
||||
sub MurmurHash
|
||||
{
|
||||
use integer;
|
||||
|
||||
my $word = shift;
|
||||
my $seed = shift;
|
||||
|
||||
# https://tanjent.livejournal.com/756623.html
|
||||
|
||||
my $m = 0x7fd652ad;
|
||||
my $r = 16;
|
||||
|
||||
my $hash = $seed;
|
||||
|
||||
$hash += 0xdeadbeef;
|
||||
|
||||
my @chars = unpack ("c*", $word);
|
||||
|
||||
my $len = length $word;
|
||||
|
||||
my $i;
|
||||
|
||||
for ($i = 0; $i < $len - 3; $i += 4)
|
||||
{
|
||||
my $c0 = $chars[$i + 0];
|
||||
my $c1 = $chars[$i + 1];
|
||||
my $c2 = $chars[$i + 2];
|
||||
my $c3 = $chars[$i + 3];
|
||||
|
||||
my $l = ($c0 << 0)
|
||||
| ($c1 << 8)
|
||||
| ($c2 << 16)
|
||||
| ($c3 << 24);
|
||||
|
||||
$hash += $l;
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> $r;
|
||||
}
|
||||
|
||||
my $rem = $len & 3;
|
||||
|
||||
if ($rem == 3)
|
||||
{
|
||||
my $c0 = $chars[$i + 0];
|
||||
my $c1 = $chars[$i + 1];
|
||||
my $c2 = $chars[$i + 2];
|
||||
my $c3 = 0;
|
||||
|
||||
my $l = ($c0 << 0)
|
||||
| ($c1 << 8)
|
||||
| ($c2 << 16)
|
||||
| ($c3 << 24);
|
||||
|
||||
$hash += $l;
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> $r;
|
||||
}
|
||||
elsif ($rem == 2)
|
||||
{
|
||||
my $c0 = $chars[$i + 0];
|
||||
my $c1 = $chars[$i + 1];
|
||||
my $c2 = 0;
|
||||
my $c3 = 0;
|
||||
|
||||
my $l = ($c0 << 0)
|
||||
| ($c1 << 8)
|
||||
| ($c2 << 16)
|
||||
| ($c3 << 24);
|
||||
|
||||
$hash += $l;
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> $r;
|
||||
}
|
||||
elsif ($rem == 1)
|
||||
{
|
||||
my $c0 = $chars[$i + 0];
|
||||
my $c1 = 0;
|
||||
my $c2 = 0;
|
||||
my $c3 = 0;
|
||||
|
||||
my $l = ($c0 << 0)
|
||||
| ($c1 << 8)
|
||||
| ($c2 << 16)
|
||||
| ($c3 << 24);
|
||||
|
||||
$hash += $l;
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> $r;
|
||||
}
|
||||
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> 10;
|
||||
$hash *= $m;
|
||||
$hash ^= ($hash & 0xffffffff) >> 17;
|
||||
|
||||
return $hash & 0xffffffff;
|
||||
}
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $seed = unpack ("N", $salt_bin); # or maybe "L" ? not enought example data to clarify
|
||||
|
||||
my $digest = MurmurHash ($word, $seed);
|
||||
|
||||
my $hash = sprintf ("%08x:%08x", $digest, $seed);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash, $salt, $word) = split (':', $line);
|
||||
|
||||
return unless defined $hash;
|
||||
return unless defined $word;
|
||||
return unless defined $salt;
|
||||
|
||||
return unless length $hash == 8;
|
||||
return unless length $salt == 8;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::Eksblowfish::Bcrypt qw (bcrypt en_base64);
|
||||
use MIME::Base64 qw (decode_base64);
|
||||
use Digest::SHA1 qw (sha1_hex);
|
||||
|
||||
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $iter = shift;
|
||||
|
||||
my $cost = "05";
|
||||
|
||||
if (length ($iter))
|
||||
{
|
||||
$cost = $iter;
|
||||
}
|
||||
|
||||
my $sha1_word = sha1_hex ($word);
|
||||
|
||||
my $hash = bcrypt ($sha1_word, sprintf ('$2a$%s$%s$', $cost, en_base64 ($salt)));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $index1 = index ($line, ":", 33);
|
||||
|
||||
return if $index1 < 1;
|
||||
|
||||
my $hash = substr ($line, 0, $index1);
|
||||
my $word = substr ($line, $index1 + 1);
|
||||
|
||||
my $index2 = index ($hash, "\$", 4);
|
||||
|
||||
my $iter = substr ($hash, 4, $index2 - 4);
|
||||
|
||||
my $plain_base64 = substr ($hash, $index2 + 1, 22);
|
||||
|
||||
# base64 mapping
|
||||
|
||||
my $base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
my $itoa64_2 = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
my $encoded = "";
|
||||
|
||||
for (my $i = 0; $i < length ($plain_base64); $i++)
|
||||
{
|
||||
my $char = substr ($plain_base64, $i, 1);
|
||||
|
||||
$encoded .= substr ($base64, index ($itoa64_2, $char), 1);
|
||||
}
|
||||
|
||||
my $salt = decode_base64 ($encoded);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $iter);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: Robert Guetzkow
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Crypt::Mode::CBC;
|
||||
use Crypt::Mode::ECB;
|
||||
|
||||
# Details of the protocol design can be found in ISO 22510:2019 and
|
||||
# application notes published by the KNX Association.
|
||||
|
||||
# ETS 5 allows a maximum of 20 characters in a password.
|
||||
# The salt is used as Secure Session Identifier, which is 2 Bytes long.
|
||||
sub module_constraints { [[0, 20], [2, 2], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub device_authentication_code
|
||||
{
|
||||
my $password = shift;
|
||||
|
||||
my $pbkdf2 = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ("HMACSHA2", 256),
|
||||
iterations => 65536,
|
||||
output_len => 16
|
||||
);
|
||||
|
||||
my $device_authentication_code = $pbkdf2->PBKDF2 ("device-authentication-code.1.secure.ip.knx.org",
|
||||
$password);
|
||||
|
||||
return $device_authentication_code;
|
||||
}
|
||||
|
||||
sub block_formatting
|
||||
{
|
||||
# Simplified block formatting function, where payload is always empty
|
||||
my $b0 = shift;
|
||||
my $associated_data = shift;
|
||||
my $associated_data_length = pack ("s>", length ($associated_data));
|
||||
my $blocks_unpadded = $associated_data_length . $associated_data;
|
||||
my $pad_len = int ((length ($blocks_unpadded) + 16 - 1) / 16) * 16;
|
||||
my $blocks_padded = $blocks_unpadded . "\0" x ($pad_len - length ($blocks_unpadded));
|
||||
|
||||
return $b0 . $blocks_padded;
|
||||
}
|
||||
|
||||
sub encrypt
|
||||
{
|
||||
# Simplified encryption that only performs steps required for the MAC, not full CCM
|
||||
my $blocks = shift;
|
||||
my $nonce = shift;
|
||||
my $key = shift;
|
||||
my $iv = "\0" x 16;
|
||||
|
||||
my $aes_cbc = Crypt::Mode::CBC->new ("AES", 0);
|
||||
my $ciphertext = $aes_cbc->encrypt ($blocks, $key, $iv);
|
||||
my $y_n = substr ($ciphertext, length ($ciphertext) - 16, 16);
|
||||
|
||||
my $aes_ecb = Crypt::Mode::ECB->new ("AES", 0);
|
||||
my $s_0 = $aes_ecb->encrypt ($nonce, $key);
|
||||
|
||||
return $y_n ^ $s_0;
|
||||
}
|
||||
|
||||
sub generate_session_response_mac
|
||||
{
|
||||
my $secure_session_identifier = shift;
|
||||
my $public_value_xor = shift;
|
||||
my $key = shift;
|
||||
|
||||
# Constants used for the cryptography in Session_Response frames
|
||||
my $knx_ip_header = pack ("H*", "061009520038");
|
||||
my $b0 = pack ("H*", "00000000000000000000000000000000");
|
||||
my $nonce = pack ("H*", "0000000000000000000000000000ff00");
|
||||
|
||||
my $associated_data = $knx_ip_header . $secure_session_identifier . $public_value_xor;
|
||||
|
||||
my $blocks = block_formatting ($b0, $associated_data);
|
||||
|
||||
return encrypt ($blocks, $nonce, $key);
|
||||
}
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
|
||||
# Parameters that would be found in the Session_Request and Session_Response frames
|
||||
my $secure_session_identifier = shift;
|
||||
my $public_value_xor = shift // random_bytes (32);
|
||||
|
||||
my $device_authentication_code = device_authentication_code ($word);
|
||||
|
||||
my $mac = generate_session_response_mac ($secure_session_identifier,
|
||||
$public_value_xor,
|
||||
$device_authentication_code);
|
||||
|
||||
my $hash = sprintf ("\$knx-ip-secure-device-authentication-code\$*%s*%s*%s",
|
||||
unpack ("H*", $secure_session_identifier),
|
||||
unpack ("H*", $public_value_xor),
|
||||
unpack ("H*", $mac));
|
||||
|
||||
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) == 4;
|
||||
|
||||
my $signature = shift @data;
|
||||
|
||||
return unless ($signature eq "\$knx-ip-secure-device-authentication-code\$");
|
||||
|
||||
my $secure_session_identifier = pack ("H*", shift @data); # 2 Bytes expected (using the "salt" for this purpose)
|
||||
my $public_value_xor = pack ("H*", shift @data); # 32 Bytes expected (xor of client's and server's public value)
|
||||
my $mac = pack ("H*", shift @data); # 16 Bytes expected
|
||||
|
||||
return unless (length ($secure_session_identifier) == 2);
|
||||
return unless (length ($public_value_xor) == 32);
|
||||
return unless (length ($mac) == 16);
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed,
|
||||
$secure_session_identifier,
|
||||
$public_value_xor);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::DES;
|
||||
use Crypt::DES_EDE3;
|
||||
use Digest::SHA qw (sha1);
|
||||
use Digest::HMAC qw (hmac);
|
||||
|
||||
sub module_constraints { [[0, 256], [40, 40], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $global_salt = shift;
|
||||
my $entry_salt = shift // random_hex_string (40);
|
||||
my $ct = shift;
|
||||
|
||||
my $global_salt_bin = pack ("H*", $global_salt);
|
||||
my $entry_salt_bin = pack ("H*", $entry_salt);
|
||||
|
||||
my $hp = sha1 ($global_salt_bin . $word);
|
||||
|
||||
my $pes = substr ($entry_salt_bin . ("\x00" x 20), 0, 20);
|
||||
|
||||
my $chp = sha1 ($hp . $entry_salt_bin);
|
||||
|
||||
my $k1 = hmac ($pes . $entry_salt_bin, $chp, \&sha1, 64);
|
||||
|
||||
my $tk = hmac ($pes, $chp, \&sha1, 64);
|
||||
|
||||
my $k2 = hmac ($tk . $entry_salt_bin, $chp, \&sha1, 64);
|
||||
|
||||
my $k = $k1 . $k2;
|
||||
|
||||
my $key = substr ($k, 0, 24);
|
||||
my $iv = substr ($k, 32, 8);
|
||||
|
||||
my $pt;
|
||||
|
||||
if (defined $ct)
|
||||
{
|
||||
my $ct_bin = pack ("H*", $ct);
|
||||
|
||||
my $ede3 = Crypt::DES_EDE3->new ($key);
|
||||
|
||||
my $ct1_bin = substr ($ct_bin, 0, 8);
|
||||
my $ct2_bin = substr ($ct_bin, 8, 8);
|
||||
|
||||
my $pt1 = $ede3->decrypt ($ct1_bin);
|
||||
|
||||
$pt1 = exclusive_or ($pt1, $iv);
|
||||
|
||||
my $pt2 = $ede3->decrypt ($ct2_bin);
|
||||
|
||||
$pt2 = exclusive_or ($pt2, $ct1_bin);
|
||||
|
||||
$pt = $pt1 . $pt2;
|
||||
|
||||
if ($pt ne "password-check\x02\x02")
|
||||
{
|
||||
$pt = "\xff" x 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$pt = "password-check\x02\x02";
|
||||
}
|
||||
|
||||
my $ede3 = Crypt::DES_EDE3->new ($key);
|
||||
|
||||
my $pt1 = substr ($pt, 0, 8);
|
||||
my $pt2 = substr ($pt, 8, 8);
|
||||
|
||||
$pt1 = exclusive_or ($pt1, $iv);
|
||||
|
||||
my $ct1_bin = $ede3->encrypt ($pt1);
|
||||
|
||||
$pt2 = exclusive_or ($pt2, $ct1_bin);
|
||||
|
||||
my $ct2_bin = $ede3->encrypt ($pt2);
|
||||
|
||||
my $ct_bin = $ct1_bin . $ct2_bin;
|
||||
|
||||
my $hash = sprintf ('$mozilla$*3DES*%s*%s*%s', unpack ("H*", $global_salt_bin), unpack ("H*", $entry_salt_bin), unpack ("H*", $ct_bin));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return unless $idx >= 0;
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 9) eq '$mozilla$';
|
||||
|
||||
my ($signature, $type, $global_salt, $entry_salt, $ct) = split '\*', $hash;
|
||||
|
||||
return unless defined $signature;
|
||||
return unless defined $type;
|
||||
return unless defined $global_salt;
|
||||
return unless defined $entry_salt;
|
||||
return unless defined $ct;
|
||||
|
||||
return unless $type eq '3DES';
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $global_salt, $entry_salt, $ct);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
sub exclusive_or
|
||||
{
|
||||
my $in1 = shift;
|
||||
my $in2 = shift;
|
||||
|
||||
my $out = "";
|
||||
|
||||
for (my $i = 0; $i < length ($in1); $i++) # $i < $len
|
||||
{
|
||||
$out .= chr (ord (substr ($in1, $i, 1)) ^ ord (substr ($in2, $i, 1)));
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::PBKDF2;
|
||||
use Crypt::CBC;
|
||||
use Digest::SHA qw (sha1);
|
||||
|
||||
sub module_constraints { [[0, 256], [40, 40], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $global_salt = shift;
|
||||
my $entry_salt = shift // random_hex_string (64);
|
||||
my $iter = shift // 10000;
|
||||
my $iv = shift // random_hex_string (32);
|
||||
my $ct = shift;
|
||||
|
||||
my $kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256),
|
||||
iterations => $iter,
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
my $global_salt_bin = pack ("H*", $global_salt);
|
||||
|
||||
my $global_key = sha1 ($global_salt_bin . $word);
|
||||
|
||||
my $entry_salt_bin = pack ("H*", $entry_salt);
|
||||
|
||||
my $entry_key = $kdf->PBKDF2 ($entry_salt_bin, $global_key);
|
||||
|
||||
my $iv_bin = pack ("H*", $iv);
|
||||
|
||||
my $pt;
|
||||
|
||||
if (defined $ct)
|
||||
{
|
||||
my $aes_cbc = Crypt::CBC->new ({
|
||||
cipher => "Crypt::Rijndael",
|
||||
iv => $iv_bin,
|
||||
key => $entry_key,
|
||||
keysize => 32,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "none"
|
||||
});
|
||||
|
||||
my $ct_bin = pack ("H*", $ct);
|
||||
|
||||
$pt = $aes_cbc->decrypt ($ct_bin);
|
||||
|
||||
if ($pt ne "password-check\x02\x02")
|
||||
{
|
||||
$pt = "\xff" x 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$pt = "password-check\x02\x02";
|
||||
}
|
||||
|
||||
my $aes_cbc = Crypt::CBC->new ({
|
||||
cipher => "Crypt::Rijndael",
|
||||
iv => $iv_bin,
|
||||
key => $entry_key,
|
||||
keysize => 32,
|
||||
literal_key => 1,
|
||||
header => "none",
|
||||
padding => "none"
|
||||
});
|
||||
|
||||
my $ct_bin = $aes_cbc->encrypt ($pt);
|
||||
|
||||
my $hash = sprintf ('$mozilla$*AES*%s*%s*%d*%s*%s', unpack ("H*", $global_salt_bin), unpack ("H*", $entry_salt_bin), $iter, unpack ("H*", $iv_bin), unpack ("H*", $ct_bin));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx = index ($line, ':');
|
||||
|
||||
return unless $idx >= 0;
|
||||
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 9) eq '$mozilla$';
|
||||
|
||||
my ($signature, $type, $global_salt, $entry_salt, $iter, $iv, $ct) = split '\*', $hash;
|
||||
|
||||
return unless defined $signature;
|
||||
return unless defined $type;
|
||||
return unless defined $global_salt;
|
||||
return unless defined $entry_salt;
|
||||
return unless defined $iter;
|
||||
return unless defined $iv;
|
||||
return unless defined $ct;
|
||||
|
||||
return unless $type eq 'AES';
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $global_salt, $entry_salt, $iter, $iv, $ct);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user