File Coverage

blib/lib/Authen/Passphrase/MySQL323.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::MySQL323 - passphrases using the MySQL v3.23 algorithm
4              
5             =head1 SYNOPSIS
6              
7             use Authen::Passphrase::MySQL323;
8              
9             $ppr = Authen::Passphrase::MySQL323->new(
10             hash_hex => "2af8a0a82c8f9086");
11              
12             $ppr = Authen::Passphrase::MySQL323->new(
13             passphrase => "passphrase");
14              
15             $hash = $ppr->hash;
16             $hash_hex = $ppr->hash_hex;
17              
18             if($ppr->match($passphrase)) { ...
19              
20             =head1 DESCRIPTION
21              
22             An object of this class encapsulates a passphrase hashed using the
23             algorithm used by MySQL from version 3.23. This is a subclass of
24             L, and this document assumes that the reader is
25             familiar with the documentation for that class.
26              
27             The MySQL v3.23 hash scheme is composed entirely of linear operations.
28             It accepts an arbitrarily long passphrase, and ignores all space
29             and tab characters. No salt is used. 62 bits of hash are generated.
30             Each character influences only a minority of the result bits, so similar
31             passphrases of the same length have noticeably similar hashes.
32              
33             In MySQL the hash is represented as a string of sixteen lowercase
34             hexadecimal digits.
35              
36             I This is not a serious cryptographic algorithm. Do not use
37             for any security purpose.
38              
39             =cut
40              
41             package Authen::Passphrase::MySQL323;
42              
43 1     1   525938 { use 5.006; }
  1         6  
  1         68  
44 1     1   8 use warnings;
  1         2  
  1         54  
45 1     1   16 use strict;
  1         3  
  1         55  
46              
47 1     1   890 use Authen::Passphrase 0.003;
  1         21  
  1         28  
48 1     1   7 use Carp qw(croak);
  1         1  
  1         133  
49 1     1   456692 use Crypt::MySQL 0.03 qw(password);
  1         1399948  
  1         176  
50              
51             our $VERSION = "0.008";
52              
53 1     1   1561 use parent "Authen::Passphrase";
  1         610  
  1         10  
54              
55             =head1 CONSTRUCTOR
56              
57             =over
58              
59             =item Authen::Passphrase::MySQL323->new(ATTR => VALUE, ...)
60              
61             Generates a new passphrase recogniser object using the MySQL v3.23
62             algorithm. The following attributes may be given:
63              
64             =over
65              
66             =item B
67              
68             The hash, as a string of eight bytes. The first and fifth bytes must
69             have their top bit clear.
70              
71             =item B
72              
73             The hash, as a string of 16 hexadecimal digits.
74              
75             =item B
76              
77             A passphrase that will be accepted.
78              
79             =back
80              
81             Either the hash or the passphrase must be given.
82              
83             =cut
84              
85             sub new {
86 6     6 1 2041 my $class = shift;
87 6         21 my $self = bless({}, $class);
88 6         10 my $passphrase;
89 6         19 while(@_) {
90 6         10 my $attr = shift;
91 6         11 my $value = shift;
92 6 100       23 if($attr eq "hash") {
    100          
    50          
93 2 50 33     16 croak "hash specified redundantly"
94             if exists($self->{hash}) ||
95             defined($passphrase);
96 2 50       13 $value =~ m#\A(?:[\x00-\x7f][\x00-\xff]{3}){2}\z#
97             or croak "not a valid MySQL v3.23 hash";
98 2         11 $self->{hash} = "$value";
99             } elsif($attr eq "hash_hex") {
100 3 50 33     21 croak "hash specified redundantly"
101             if exists($self->{hash}) ||
102             defined($passphrase);
103 3 50       17 $value =~ m#\A(?:[0-7][0-9A-Fa-f]{7}){2}\z#
104             or croak "\"$value\" is not a valid ".
105             "hex MySQL v3.23 hash";
106 3         18 $self->{hash} = pack("H*", $value);
107             } elsif($attr eq "passphrase") {
108 1 50 33     20 croak "passphrase specified redundantly"
109             if exists($self->{hash}) ||
110             defined($passphrase);
111 1         5 $passphrase = $value;
112             } else {
113 0         0 croak "unrecognised attribute `$attr'";
114             }
115             }
116 6 100       19 $self->{hash} = $self->_hash_of($passphrase) if defined $passphrase;
117 6 50       19 croak "hash not specified" unless exists $self->{hash};
118 6         14 return $self;
119             }
120              
121             =back
122              
123             =head1 METHODS
124              
125             =over
126              
127             =item $ppr->hash
128              
129             Returns the hash value, as a string of eight bytes.
130              
131             =cut
132              
133             sub hash {
134 6     6 1 408 my($self) = @_;
135 6         23 return $self->{hash};
136             }
137              
138             =item $ppr->hash_hex
139              
140             Returns the hash value, as a string of 16 hexadecimal digits.
141              
142             =cut
143              
144             sub hash_hex {
145 6     6 1 1819 my($self) = @_;
146 6         43 return unpack("H*", $self->{hash});
147             }
148              
149             =item $ppr->match(PASSPHRASE)
150              
151             This method is part of the standard L interface.
152              
153             =cut
154              
155             sub _hash_of {
156 26     26   43 my($self, $passphrase) = @_;
157 26         272 return pack("H*", password($passphrase));
158             }
159              
160             sub match {
161 25     25 1 10836 my($self, $passphrase) = @_;
162 25         39 return $self->_hash_of($passphrase) eq $self->{hash};
163             }
164              
165             =back
166              
167             =head1 SEE ALSO
168              
169             L,
170             L
171              
172             =head1 AUTHOR
173              
174             Andrew Main (Zefram)
175              
176             =head1 COPYRIGHT
177              
178             Copyright (C) 2006, 2007, 2009, 2010, 2012
179             Andrew Main (Zefram)
180              
181             =head1 LICENSE
182              
183             This module is free software; you can redistribute it and/or modify it
184             under the same terms as Perl itself.
185              
186             =cut
187              
188             1;