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 to64
16{
17  my $v = shift;
18  my $n = shift;
19
20  my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
21
22  my $ret = "";
23
24  while (($n - 1) >= 0)
25  {
26    $n = $n - 1;
27
28    $ret .= substr ($itoa64, $v & 0x3f, 1);
29
30    $v = $v >> 6;
31  }
32
33  return $ret
34}
35
36sub aix_ssha1_pbkdf2
37{
38  my $word_buf   = shift;
39  my $salt_buf   = shift;
40  my $iterations = shift;
41
42  my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1');
43
44  my $pbkdf2 = Crypt::PBKDF2->new (
45    hasher       => $hasher,
46    iterations   => $iterations,
47  );
48
49  my $hash_buf = $pbkdf2->PBKDF2 ($salt_buf, $word_buf);
50
51  my $tmp_hash = "";
52
53  $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);
54  $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);
55  $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);
56  $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);
57  $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);
58  $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);
59  $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 18, 1))) << 16) | (int (ord (substr ($hash_buf, 19, 1))) << 8)                                          , 3);
60
61  return $tmp_hash;
62}
63
64sub module_generate_hash
65{
66  my $word = shift;
67  my $salt = shift;
68  my $iter = shift // 64;
69
70  my $hash_buf = aix_ssha1_pbkdf2 ($word, $salt, $iter);
71
72  my $hash = sprintf ("{ssha1}%02i\$%s\$%s", log ($iter) / log (2), $salt, $hash_buf);
73
74  return $hash;
75}
76
77sub module_verify_hash
78{
79  my $line = shift;
80
81  my $index1 = index ($line, ":");
82  my $hash_in = substr ($line, 0, $index1);
83
84  return if $index1 < 1;
85
86  my $word = substr ($line, $index1 + 1);
87
88  my $index2 =  index ($hash_in, "}");
89  my $index3 =  index ($hash_in, "\$");
90  my $index4 = rindex ($hash_in, "\$");
91
92  my $salt = substr ($hash_in, $index3 + 1, $index4 - $index3 - 1);
93
94  my $iter = substr ($hash_in, $index2 + 1, $index3 - $index2 - 1);
95
96  return unless defined $salt;
97  return unless defined $word;
98  return unless defined $iter;
99
100  $word = pack_if_HEX_notation ($word);
101
102  my $new_hash = module_generate_hash ($word, $salt, 1 << int ($iter));
103
104  return ($new_hash, $word);
105}
106
1071;
108