2023-03-15 20:22:10 +00:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
|
|
|
|
##
|
|
|
|
## Author......: See docs/credits.txt
|
|
|
|
## License.....: MIT
|
|
|
|
##
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use Digest::SHA qw (sha256_hex);
|
|
|
|
use Crypt::CBC;
|
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
sub module_constraints { [[0, 55], [-1, -1], [0, 55], [-1, -1], [-1, -1]] }
|
2023-03-15 20:22:10 +00:00
|
|
|
|
|
|
|
sub calculate_padding
|
|
|
|
{
|
2023-04-27 16:16:07 +00:00
|
|
|
my $length = shift;
|
|
|
|
my $blocksize = shift // 32;
|
|
|
|
my $minpadding = shift // 16;
|
2023-03-15 20:22:10 +00:00
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
my $padded_len = $length+$minpadding;
|
|
|
|
my $finalpadded = (($padded_len - 1) | ($blocksize - 1)) + 1;
|
2023-03-15 20:22:10 +00:00
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
return $finalpadded - $length;
|
2023-03-15 20:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub module_generate_hash
|
|
|
|
{
|
|
|
|
my $word = shift;
|
2023-04-27 16:16:07 +00:00
|
|
|
my $total_len = (length ($word) * 2) + 8 + 64;
|
|
|
|
my $padding = shift // random_hex_string (calculate_padding ($total_len));
|
2023-03-15 20:22:10 +00:00
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
if (length $padding == 0) {
|
|
|
|
$padding = random_hex_string (calculate_padding ($total_len));
|
|
|
|
}
|
2023-03-15 20:22:10 +00:00
|
|
|
|
|
|
|
my $digest = sha256_hex ($word);
|
2023-04-27 16:16:07 +00:00
|
|
|
my $len = sprintf ("%02d", length ($word));
|
|
|
|
my $paddedlen = sprintf ("%02x000000", $len);
|
|
|
|
my $hexofword = unpack "H*", $word;
|
2023-03-15 20:22:10 +00:00
|
|
|
my $plaintext = $paddedlen . $hexofword . $digest . $padding;
|
|
|
|
|
|
|
|
my $aes = Crypt::CBC->new ({
|
|
|
|
key => pack ("H*", $digest),
|
|
|
|
cipher => "Crypt::Rijndael",
|
|
|
|
iv => => "\x00" x 16,
|
|
|
|
literal_key => 1,
|
|
|
|
header => "none",
|
|
|
|
keysize => 32,
|
|
|
|
padding => "none",
|
|
|
|
});
|
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
my $ciphertext = $aes->encrypt (pack ("H*", $plaintext));
|
|
|
|
my $hash = sprintf ("S:\"Config Passphrase\"=02:%s", unpack ("H*", $ciphertext));
|
2023-03-15 20:22:10 +00:00
|
|
|
|
|
|
|
return $hash
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_aes
|
|
|
|
{
|
2023-04-27 16:16:07 +00:00
|
|
|
my $word_packed = shift;
|
|
|
|
my $key = sha256_hex ($word_packed);
|
2023-03-15 20:22:10 +00:00
|
|
|
|
2023-04-27 16:16:07 +00:00
|
|
|
my $aes = Crypt::CBC->new ({
|
2023-03-15 20:22:10 +00:00
|
|
|
key => pack ("H*", $key),
|
|
|
|
cipher => "Crypt::Rijndael",
|
|
|
|
iv => => "\x00" x 16,
|
|
|
|
literal_key => 1,
|
|
|
|
header => "none",
|
|
|
|
keysize => 32,
|
|
|
|
padding => "none",
|
|
|
|
});
|
2023-04-27 16:16:07 +00:00
|
|
|
|
2023-03-15 20:22:10 +00:00
|
|
|
return $aes
|
|
|
|
}
|
|
|
|
|
|
|
|
sub module_verify_hash
|
|
|
|
{
|
|
|
|
my $line = shift;
|
|
|
|
|
|
|
|
my ($hash, $word) = $line=~ /S:.Config.Passphrase.=02:(.*):(.*)/;
|
|
|
|
|
|
|
|
return unless defined $hash;
|
|
|
|
return unless defined $word;
|
|
|
|
|
|
|
|
my $word_packed = pack_if_HEX_notation ($word);
|
2023-04-27 16:16:07 +00:00
|
|
|
my $decrypted = get_aes ($word_packed)->decrypt (pack"H*", $hash);
|
|
|
|
my $plaintext_hex = unpack "H*", $decrypted;
|
|
|
|
my $passlen = hex (substr ($plaintext_hex, 0, 2));
|
|
|
|
my $padding = substr ($plaintext_hex, 8 + 2 * $passlen + 64);
|
2023-03-15 20:22:10 +00:00
|
|
|
|
|
|
|
my $new_hash = module_generate_hash ($word_packed,$padding);
|
|
|
|
|
|
|
|
return ($new_hash, $word);
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|