1#!/usr/bin/env perl
2
3##
4## Author......: See docs/credits.txt
5## License.....: MIT
6##
7
8use strict;
9use warnings;
10
11use Crypt::PBKDF2;
12
13sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
14
15sub module_generate_hash
16{
17  my $word = shift;
18  my $salt = shift;
19  my $iter = shift;
20
21  my $iterations = 64;
22
23  if (length ($iter))
24  {
25    $iterations = 1 << int ($iter);
26  }
27
28  my $digest = aix_ssha512_pbkdf2 ($word, $salt, $iterations);
29
30  my $hash = sprintf ("{ssha512}%02i\$%s\$%s", log ($iterations) / log (2), $salt, $digest);
31
32  return $hash;
33}
34
35sub module_verify_hash
36{
37  my $line = shift;
38
39  my ($hash, $word) = split (':', $line);
40
41  return unless defined $hash;
42  return unless defined $word;
43
44  my $signature = substr ($hash, 0, 9);
45
46  return unless ($signature eq "{ssha512}");
47
48  $hash = substr ($hash, 9);
49
50  my @data = split ('\$', $hash);
51
52  return unless scalar @data == 3;
53
54  my $iter   = shift (@data);
55  my $salt   = shift @data;
56  my $digest = shift @data;
57
58  my $word_packed = pack_if_HEX_notation ($word);
59
60  my $new_hash = module_generate_hash ($word_packed, $salt, $iter);
61
62  return ($new_hash, $word);
63}
64
65sub aix_ssha512_pbkdf2
66{
67  my $word_buf   = shift;
68  my $salt_buf   = shift;
69  my $iterations = shift;
70
71  my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512);
72
73  my $pbkdf2 = Crypt::PBKDF2->new (
74    hasher       => $hasher,
75    iterations   => $iterations,
76  );
77
78  my $hash_buf = $pbkdf2->PBKDF2 ($salt_buf, $word_buf);
79
80  my $tmp_hash = "";
81
82  $tmp_hash .= to64 ((int (ord (substr ($hash_buf,  0, 1))) << 16) | (int (ord (substr ($hash_buf,  1, 1))) << 8) | (int (ord (substr ($hash_buf,  2, 1)))), 4);
83  $tmp_hash .= to64 ((int (ord (substr ($hash_buf,  3, 1))) << 16) | (int (ord (substr ($hash_buf,  4, 1))) << 8) | (int (ord (substr ($hash_buf,  5, 1)))), 4);
84  $tmp_hash .= to64 ((int (ord (substr ($hash_buf,  6, 1))) << 16) | (int (ord (substr ($hash_buf,  7, 1))) << 8) | (int (ord (substr ($hash_buf,  8, 1)))), 4);
85  $tmp_hash .= to64 ((int (ord (substr ($hash_buf,  9, 1))) << 16) | (int (ord (substr ($hash_buf, 10, 1))) << 8) | (int (ord (substr ($hash_buf, 11, 1)))), 4);
86  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 12, 1))) << 16) | (int (ord (substr ($hash_buf, 13, 1))) << 8) | (int (ord (substr ($hash_buf, 14, 1)))), 4);
87  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 15, 1))) << 16) | (int (ord (substr ($hash_buf, 16, 1))) << 8) | (int (ord (substr ($hash_buf, 17, 1)))), 4);
88  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 18, 1))) << 16) | (int (ord (substr ($hash_buf, 19, 1))) << 8) | (int (ord (substr ($hash_buf, 20, 1)))), 4);
89  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 21, 1))) << 16) | (int (ord (substr ($hash_buf, 22, 1))) << 8) | (int (ord (substr ($hash_buf, 23, 1)))), 4);
90  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 24, 1))) << 16) | (int (ord (substr ($hash_buf, 25, 1))) << 8) | (int (ord (substr ($hash_buf, 26, 1)))), 4);
91  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 27, 1))) << 16) | (int (ord (substr ($hash_buf, 28, 1))) << 8) | (int (ord (substr ($hash_buf, 29, 1)))), 4);
92  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 30, 1))) << 16) | (int (ord (substr ($hash_buf, 31, 1))) << 8) | (int (ord (substr ($hash_buf, 32, 1)))), 4);
93  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 33, 1))) << 16) | (int (ord (substr ($hash_buf, 34, 1))) << 8) | (int (ord (substr ($hash_buf, 35, 1)))), 4);
94  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 36, 1))) << 16) | (int (ord (substr ($hash_buf, 37, 1))) << 8) | (int (ord (substr ($hash_buf, 38, 1)))), 4);
95  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 39, 1))) << 16) | (int (ord (substr ($hash_buf, 40, 1))) << 8) | (int (ord (substr ($hash_buf, 41, 1)))), 4);
96  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 42, 1))) << 16) | (int (ord (substr ($hash_buf, 43, 1))) << 8) | (int (ord (substr ($hash_buf, 44, 1)))), 4);
97  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 45, 1))) << 16) | (int (ord (substr ($hash_buf, 46, 1))) << 8) | (int (ord (substr ($hash_buf, 47, 1)))), 4);
98  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 48, 1))) << 16) | (int (ord (substr ($hash_buf, 49, 1))) << 8) | (int (ord (substr ($hash_buf, 50, 1)))), 4);
99  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 51, 1))) << 16) | (int (ord (substr ($hash_buf, 52, 1))) << 8) | (int (ord (substr ($hash_buf, 53, 1)))), 4);
100  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 54, 1))) << 16) | (int (ord (substr ($hash_buf, 55, 1))) << 8) | (int (ord (substr ($hash_buf, 56, 1)))), 4);
101  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 57, 1))) << 16) | (int (ord (substr ($hash_buf, 58, 1))) << 8) | (int (ord (substr ($hash_buf, 59, 1)))), 4);
102  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 60, 1))) << 16) | (int (ord (substr ($hash_buf, 61, 1))) << 8) | (int (ord (substr ($hash_buf, 62, 1)))), 4);
103  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 63, 1))) << 16)                                                                                         , 2);
104
105  return $tmp_hash;
106}
107
108sub to64
109{
110  my $v = shift;
111  my $n = shift;
112
113  my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
114
115  my $ret = "";
116
117  while (($n - 1) >= 0)
118  {
119    $n = $n - 1;
120
121    $ret .= substr ($itoa64, $v & 0x3f, 1);
122
123    $v = $v >> 6;
124  }
125
126  return $ret
127}
128
1291;
130