1#!/usr/bin/env perl
2
3##
4## Author......: See docs/credits.txt
5## License.....: MIT
6##
7
8use strict;
9use warnings;
10
11use Convert::EBCDIC qw (ascii2ebcdic);
12use Crypt::DES;
13
14sub module_constraints { [[0, 8], [1, 8], [-1, -1], [-1, -1], [-1, -1]] }
15
16sub racf_hash
17{
18  my ($username, $password) = @_;
19
20  $username = substr ($username . " " x 8, 0, 8);
21  $password = substr ($password . " " x 8, 0, 8);
22
23  my $username_ebc = ascii2ebcdic ($username);
24  my $password_ebc = ascii2ebcdic ($password);
25
26  my @pw = split ("", $password_ebc);
27
28  for (my $i = 0; $i < 8; $i++)
29  {
30    $pw[$i] = unpack ("C", $pw[$i]);
31    $pw[$i] ^= 0x55;
32    $pw[$i] <<= 1;
33    $pw[$i] = pack ("C", $pw[$i] & 0xff);
34  }
35
36  my $key = join ("", @pw);
37
38  my $cipher = new Crypt::DES $key;
39
40  my $ciphertext = $cipher->encrypt ($username_ebc);
41
42  my $ct = unpack ("H16", $ciphertext);
43
44  return $ct;
45}
46
47sub module_generate_hash
48{
49  my $word = shift;
50  my $salt = shift;
51
52  my $hash_buf = racf_hash (uc $salt, $word);
53
54  my $hash = sprintf ('$racf$*%s*%s', uc $salt, uc $hash_buf);
55
56  return $hash;
57}
58
59sub module_verify_hash
60{
61  my $line = shift;
62
63  my @line_elements = split (":", $line);
64
65  return if scalar @line_elements < 2;
66
67  my $hash_in = shift @line_elements;
68
69  my $word = join (":", @line_elements);
70
71  # check signature
72
73  my @hash_elements = split ('\*', $hash_in);
74
75  return unless ($hash_elements[0] eq '$racf$');
76
77  my $salt = $hash_elements[1];
78
79  return unless defined $salt;
80  return unless defined $word;
81
82  $word = pack_if_HEX_notation ($word);
83
84  my $new_hash = module_generate_hash ($word, $salt);
85
86  return ($new_hash, $word);
87}
88
891;
90