1#!/usr/bin/env perl
2
3##
4## Author......: See docs/credits.txt
5## License.....: MIT
6##
7
8use strict;
9use warnings;
10
11use Digest::MD5 qw (md5);
12use POSIX       qw (ceil);
13
14sub module_constraints { [[-1, -1], [-1, -1], [0, 55], [1, 4], [-1, -1]] }
15
16sub pseudo_base64
17{
18  my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
19
20  my $md5 = shift;
21  my $s64 = "";
22  for my $i (0..3) {
23      my $v = unpack "V", substr ($md5, $i*4, 4);
24      for (1..4) {
25          $s64 .= substr ($itoa64, $v & 0x3f, 1);
26          $v >>= 6;
27      }
28  }
29  return $s64;
30}
31
32sub module_generate_hash
33{
34  my $word = shift;
35  my $salt = shift;
36
37  my $word_salt = $word . $salt;
38
39  my $word_salt_len = length ($word_salt);
40
41  my $pad_len = ceil ($word_salt_len / 16) * 16;
42
43  my $digest = md5 ($word_salt . "\0" x ($pad_len - $word_salt_len));
44
45  my $hash = sprintf ("%s:%s", pseudo_base64 ($digest), $salt);
46
47  return $hash;
48}
49
50sub module_verify_hash
51{
52  my $line = shift;
53
54  my ($hash, $salt, $word) = split (':', $line);
55
56  return unless defined $hash;
57  return unless defined $salt;
58  return unless defined $word;
59
60  my $word_packed = pack_if_HEX_notation ($word);
61
62  my $new_hash = module_generate_hash ($word_packed, $salt);
63
64  return ($new_hash, $word);
65}
66
671;
68