File Coverage

blib/lib/Authen/Passphrase/MySQL41.pm
Criterion Covered Total %
statement 47 48 97.9
branch 13 20 65.0
condition 3 9 33.3
subroutine 12 12 100.0
pod 4 4 100.0
total 79 93 84.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Authen::Passphrase::MySQL41 - passphrases using the MySQL v4.1 algorithm
4              
5             =head1 SYNOPSIS
6              
7             use Authen::Passphrase::MySQL41;
8              
9             $ppr = Authen::Passphrase::MySQL41->new(
10             hash_hex => "9CD12C48C4C5DD62914B".
11             "3FABB93131746E9E9115");
12              
13             $ppr = Authen::Passphrase::MySQL41->new(
14             passphrase => "passphrase");
15              
16             $hash = $ppr->hash;
17             $hash_hex = $ppr->hash_hex;
18              
19             if($ppr->match($passphrase)) { ...
20              
21             =head1 DESCRIPTION
22              
23             An object of this class encapsulates a passphrase hashed using the
24             algorithm used by MySQL from version 4.1. This is a subclass of
25             L, and this document assumes that the reader is
26             familiar with the documentation for that class.
27              
28             The MySQL v4.1 hash scheme is based on the SHA-1 digest algorithm.
29             The passphrase is first hashed using SHA-1, then the output of that
30             stage is hashed using SHA-1 again. The final hash is the output of the
31             second SHA-1. No salt is used.
32              
33             In MySQL the hash is represented as a "B<*>" followed by 40 uppercase
34             hexadecimal digits.
35              
36             The lack of salt is a weakness in this scheme. Salted SHA-1 is a better
37             scheme; see L.
38              
39             =cut
40              
41             package Authen::Passphrase::MySQL41;
42              
43 1     1   439531 { use 5.006; }
  1         4  
  1         46  
44 1     1   6 use warnings;
  1         2  
  1         75  
45 1     1   10 use strict;
  1         2  
  1         35  
46              
47 1     1   645 use Authen::Passphrase 0.003;
  1         19  
  1         29  
48 1     1   6 use Carp qw(croak);
  1         2  
  1         52  
49 1     1   39546 use Digest::SHA qw(sha1);
  1         8079  
  1         125  
50              
51             our $VERSION = "0.008";
52              
53 1     1   891 use parent "Authen::Passphrase";
  1         298  
  1         6  
54              
55             =head1 CONSTRUCTOR
56              
57             =over
58              
59             =item Authen::Passphrase::MySQL41->new(ATTR => VALUE, ...)
60              
61             Generates a new passphrase recogniser object using the MySQL v4.1
62             algorithm. The following attributes may be given:
63              
64             =over
65              
66             =item B
67              
68             The hash, as a string of 20 bytes.
69              
70             =item B
71              
72             The hash, as a string of 40 hexadecimal digits.
73              
74             =item B
75              
76             A passphrase that will be accepted.
77              
78             =back
79              
80             Either the hash or the passphrase must be given.
81              
82             =cut
83              
84             sub new {
85 6     6 1 2635 my $class = shift;
86 6         23 my $self = bless({}, $class);
87 6         9 my $passphrase;
88 6         21 while(@_) {
89 6         12 my $attr = shift;
90 6         10 my $value = shift;
91 6 100       26 if($attr eq "hash") {
    100          
    50          
92 2 50 33     17 croak "hash specified redundantly"
93             if exists($self->{hash}) ||
94             defined($passphrase);
95 2 50       10 $value =~ m#\A[\x00-\xff]{20}\z#
96             or croak "not a valid MySQL v4.1 hash";
97 2         10 $self->{hash} = "$value";
98             } elsif($attr eq "hash_hex") {
99 3 50 33     25 croak "hash specified redundantly"
100             if exists($self->{hash}) ||
101             defined($passphrase);
102 3 50       15 $value =~ m#\A[0-9A-Fa-f]{40}\z#
103             or croak "\"$value\" is not a valid ".
104             "hex MySQL v4.1 hash";
105 3         20 $self->{hash} = pack("H*", $value);
106             } elsif($attr eq "passphrase") {
107 1 50 33     19 croak "passphrase specified redundantly"
108             if exists($self->{hash}) ||
109             defined($passphrase);
110 1         5 $passphrase = $value;
111             } else {
112 0         0 croak "unrecognised attribute `$attr'";
113             }
114             }
115 6 100       22 $self->{hash} = $self->_hash_of($passphrase) if defined $passphrase;
116 6 50       19 croak "hash not specified" unless exists $self->{hash};
117 6         15 return $self;
118             }
119              
120             =back
121              
122             =head1 METHODS
123              
124             =over
125              
126             =item $ppr->hash
127              
128             Returns the hash value, as a string of 20 bytes.
129              
130             =cut
131              
132             sub hash {
133 6     6 1 838 my($self) = @_;
134 6         26 return $self->{hash};
135             }
136              
137             =item $ppr->hash_hex
138              
139             Returns the hash value, as a string of 40 uppercase hexadecimal digits.
140              
141             =cut
142              
143             sub hash_hex {
144 6     6 1 2024 my($self) = @_;
145 6         50 return uc(unpack("H*", $self->{hash}));
146             }
147              
148             =item $ppr->match(PASSPHRASE)
149              
150             This method is part of the standard L interface.
151              
152             =cut
153              
154             sub _hash_of {
155 26     26   30 my($self, $passphrase) = @_;
156 26         335 return sha1(sha1($passphrase));
157             }
158              
159             sub match {
160 25     25 1 10031 my($self, $passphrase) = @_;
161 25         53 return $self->_hash_of($passphrase) eq $self->{hash};
162             }
163              
164             =back
165              
166             =head1 SEE ALSO
167              
168             L,
169             L
170              
171             =head1 AUTHOR
172              
173             Andrew Main (Zefram)
174              
175             =head1 COPYRIGHT
176              
177             Copyright (C) 2006, 2007, 2009, 2010, 2012
178             Andrew Main (Zefram)
179              
180             =head1 LICENSE
181              
182             This module is free software; you can redistribute it and/or modify it
183             under the same terms as Perl itself.
184              
185             =cut
186              
187             1;