File Coverage

blib/lib/Crypt/PBKDF2.pm
Criterion Covered Total %
statement 129 140 92.1
branch 32 48 66.6
condition 12 21 57.1
subroutine 30 31 96.7
pod 9 10 90.0
total 212 250 84.8


line stmt bran cond sub pod time code
1             package Crypt::PBKDF2;
2             # ABSTRACT: The PBKDF2 password hashing algorithm.
3             our $VERSION = '0.160410'; # VERSION
4             our $AUTHORITY = 'cpan:ARODLAND'; # AUTHORITY
5 6     6   89386 use Moo 2;
  6         57350  
  6         30  
6 6     6   8987 use strictures 2;
  6         7755  
  6         203  
7 6     6   3277 use namespace::autoclean;
  6         60137  
  6         20  
8 6     6   2856 use MIME::Base64 ();
  6         3905  
  6         149  
9 6     6   27 use Carp qw(croak);
  6         7  
  6         262  
10 6     6   22 use Module::Runtime;
  6         9  
  6         32  
11 6     6   124 use Try::Tiny;
  6         8  
  6         234  
12 6     6   3079 use Type::Tiny;
  6         83293  
  6         261  
13 6     6   3563 use Types::Standard qw(Str Int HashRef ConsumerOf);
  6         219855  
  6         60  
14 6     6   4738 use Scalar::Util qw(blessed);
  6         9  
  6         9912  
15              
16             sub BUILD {
17 1044     1044 0 140510 my ($self) = @_;
18 1044         15092 $self->hasher; # Force instantiation, so we get errors ASAP
19             }
20              
21              
22             has hash_class => (
23             is => 'ro',
24             isa => Str,
25             default => 'HMACSHA1',
26             predicate => 'has_hash_class',
27             );
28              
29              
30             has hash_args => (
31             is => 'ro',
32             isa => HashRef,
33             default => sub { +{} },
34             predicate => 'has_hash_args',
35             );
36              
37              
38             has hasher => (
39             is => 'ro',
40             isa => ConsumerOf['Crypt::PBKDF2::Hash'],
41             lazy => 1,
42             default => sub { shift->_lazy_hasher },
43             );
44              
45             has _lazy_hasher => (
46             is => 'ro',
47             isa => ConsumerOf['Crypt::PBKDF2::Hash'],
48             lazy => 1,
49             init_arg => undef,
50             predicate => 'has_lazy_hasher',
51             builder => '_build_hasher',
52             );
53              
54             sub _build_hasher {
55 20     20   2998 my ($self) = @_;
56 20         59 my $class = $self->hash_class;
57 20 50       76 if ($class !~ s/^\+//) {
58 20         50 $class = "Crypt::PBKDF2::Hash::$class";
59             }
60 20         51 my $hash_args = $self->hash_args;
61              
62 20         77 return Module::Runtime::use_module($class)->new( %$hash_args );
63             }
64              
65              
66             has iterations => (
67             is => 'ro',
68             isa => Int,
69             default => 1000,
70             );
71              
72              
73             has output_len => (
74             is => 'ro',
75             isa => Int,
76             predicate => 'has_output_len',
77             );
78              
79              
80             has salt_len => (
81             is => 'ro',
82             isa => Int,
83             default => 4,
84             );
85              
86             sub _random_salt {
87 1023     1023   955 my ($self) = @_;
88 1023         894 my $ret = "";
89 1023         2786 for my $n (1 .. $self->salt_len) {
90 4680         5418 $ret .= chr(int rand 256);
91             }
92 1023         1754 return $ret;
93             }
94              
95              
96             has encoding => (
97             is => 'ro',
98             isa => Str,
99             default => 'ldap',
100             );
101              
102              
103             has length_limit => (
104             is => 'ro',
105             isa => Int,
106             predicate => 'has_length_limit',
107             );
108              
109              
110             sub generate {
111 1023     1023 1 407346 my ($self, $password, $salt) = @_;
112 1023 50       3351 $salt = $self->_random_salt unless defined $salt;
113              
114 1023 100 100     2874 if ($self->has_length_limit and length($password) > $self->length_limit) {
115 1         141 croak "Password exceeds length limit";
116             }
117              
118 1022         1676 my $hash = $self->PBKDF2($salt, $password);
119 1022         1899 return $self->encode_string($salt, $hash);
120             }
121              
122              
123             sub validate {
124 1023     1023 1 3893 my ($self, $hashed, $password) = @_;
125              
126 1023 100 100     2221 if ($self->has_length_limit and length($password) > $self->length_limit) {
127 1         71 croak "Password exceeds length limit";
128             }
129              
130 1022         1375 my $info = $self->decode_string($hashed);
131              
132             my $hasher = try {
133 1022     1022   26107 $self->hasher_from_algorithm($info->{algorithm}, $info->{algorithm_options});
134             } catch {
135 0 0   0   0 my $opts = defined($info->{algorithm_options}) ? " (options ''$info->{algorithm_options}'')" : "";
136 0         0 croak "Couldn't construct hasher for ''$info->{algorithm}''$opts: $_";
137 1022         6626 };
138              
139             my $checker = $self->clone(
140             hasher => $hasher,
141             iterations => $info->{iterations},
142 1022         18190 output_len => length($info->{hash}),
143             );
144              
145 1022         20495 my $check_hash = $checker->PBKDF2($info->{salt}, $password);
146              
147 1022         6639 return ($check_hash eq $info->{hash});
148             }
149              
150              
151             sub PBKDF2 {
152 5053     5053 1 6580 my ($self, $salt, $password) = @_;
153 5053         7559 my $iterations = $self->iterations;
154 5053         93559 my $hasher = $self->hasher;
155 5053   66     34133 my $output_len = $self->output_len || $hasher->hash_len;
156              
157 5053         8188 my $hLen = $hasher->hash_len;
158 5053         6911 my $l = int($output_len / $hLen);
159 5053         4144 my $r = $output_len % $hLen;
160              
161 5053 50 33     13833 if ($l > 0xffffffff or $l == 0xffffffff && $r > 0) {
      33        
162 0         0 croak "output_len too large for PBKDF2";
163             }
164              
165 5053         3458 my $output;
166              
167 5053         7806 for my $i (1 .. $l) {
168 5050         7365 $output .= $self->_PBKDF2_F($hasher, $salt, $password, $iterations, $i);
169             }
170              
171 5053 100       6757 if ($r) {
172 9         25 $output .= substr( $self->_PBKDF2_F($hasher, $salt, $password, $iterations, $l + 1), 0, $r);
173             }
174              
175 5053         15393 return $output;
176             }
177              
178              
179             sub PBKDF2_base64 {
180 1000     1000 1 1041 my $self = shift;
181              
182 1000         1667 return MIME::Base64::encode( $self->PBKDF2(@_), "" );
183             }
184              
185              
186             sub PBKDF2_hex {
187 1009     1009 1 2802 my $self = shift;
188 1009         1671 return unpack "H*", $self->PBKDF2(@_);
189             }
190              
191             sub _PBKDF2_F {
192 5059     5059   6033 my ($self, $hasher, $salt, $password, $iterations, $i) = @_;
193 5059         16992 my $result =
194             my $hash =
195             $hasher->generate( $salt . pack("N", $i), $password );
196              
197 5059         8197 for my $iter (2 .. $iterations) {
198 209650         254751 $hash = $hasher->generate( $hash, $password );
199 209650         198570 $result ^= $hash;
200             }
201              
202 5059         10789 return $result;
203             }
204              
205              
206             sub encode_string {
207 1022     1022 1 1054 my ($self, $salt, $hash) = @_;
208 1022 100       2575 if ($self->encoding eq 'crypt') {
    50          
209 511         785 return $self->_encode_string_cryptlike($salt, $hash);
210             } elsif ($self->encoding eq 'ldap') {
211 511         802 return $self->_encode_string_ldaplike($salt, $hash);
212             } else {
213 0         0 die "Unknown setting '", $self->encoding, "' for encoding";
214             }
215             }
216              
217             sub _encode_string_cryptlike {
218 511     511   544 my ($self, $salt, $hash) = @_;
219 511         8308 my $hasher = $self->hasher;
220 511         3312 my $hasher_class = blessed($hasher);
221 511 50 33     2569 if (!defined $hasher_class || $hasher_class !~ s/^Crypt::PBKDF2::Hash:://) {
222 0         0 croak "Can't ''encode_string'' with a hasher class outside of Crypt::PBKDF2::Hash::*";
223             }
224              
225 511         1020 my $algo_string = $hasher->to_algo_string;
226 511 100       786 $algo_string = defined($algo_string) ? "{$algo_string}" : "";
227              
228 511         3223 return '$PBKDF2$' . "$hasher_class$algo_string:" . $self->iterations . ':'
229             . MIME::Base64::encode($salt, "") . '$'
230             . MIME::Base64::encode($hash, "");
231             }
232              
233             sub _encode_string_ldaplike {
234 511     511   428 my ($self, $salt, $hash) = @_;
235 511         8253 my $hasher = $self->hasher;
236 511         3208 my $hasher_class = blessed($hasher);
237 511 50 33     2371 if (!defined $hasher_class || $hasher_class !~ s/^Crypt::PBKDF2::Hash:://) {
238 0         0 croak "Can't ''encode_string'' with a hasher class outside of Crypt::PBKDF2::Hash::*";
239             }
240              
241 511         1056 my $algo_string = $hasher->to_algo_string;
242 511 100       836 $algo_string = defined($algo_string) ? "+$algo_string" : "";
243              
244 511         1408 return '{X-PBKDF2}' . "$hasher_class$algo_string:"
245             . $self->_b64_encode_int32($self->iterations) . ':'
246             . MIME::Base64::encode($salt, "") . ':'
247             . MIME::Base64::encode($hash, "");
248             }
249              
250              
251             sub decode_string {
252 1022     1022 1 860 my ($self, $hashed) = @_;
253 1022 100       2567 if ($hashed =~ /^\$PBKDF2\$/) {
    50          
254 511         785 return $self->_decode_string_cryptlike($hashed);
255             } elsif ($hashed =~ /^\{X-PBKDF2}/i) {
256 511         805 return $self->_decode_string_ldaplike($hashed);
257             } else {
258 0         0 croak "Unrecognized hash";
259             }
260             }
261              
262             sub _decode_string_cryptlike {
263 511     511   421 my ($self, $hashed) = @_;
264 511 50       993 if ($hashed !~ /^\$PBKDF2\$/) {
265 0         0 croak "Unrecognized hash";
266             }
267              
268 511 50       2575 if (my ($algorithm, $opts, $iterations, $salt, $hash) = $hashed =~
269             /^\$PBKDF2\$([^:}]+)(?:\{([^}]+)\})?:(\d+):([^\$]+)\$(.*)/) {
270             return {
271 511         3040 algorithm => $algorithm,
272             algorithm_options => $opts,
273             iterations => $iterations,
274             salt => MIME::Base64::decode($salt),
275             hash => MIME::Base64::decode($hash),
276             }
277             } else {
278 0         0 croak "Invalid format";
279             }
280             }
281              
282             sub _decode_string_ldaplike {
283 511     511   414 my ($self, $hashed) = @_;
284 511 50       953 if ($hashed !~ /^\{X-PBKDF2}/i) {
285 0         0 croak "Unrecognized hash";
286             }
287              
288 511 50       2936 if (my ($algo_str, $iterations, $salt, $hash) = $hashed =~
289             /^\{X-PBKDF2}([^:]+):([^:]{6}):([^\$]+):(.*)/i) {
290 511         910 my ($algorithm, $opts) = split /\+/, $algo_str;
291             return {
292 511         923 algorithm => $algorithm,
293             algorithm_options => $opts,
294             iterations => $self->_b64_decode_int32($iterations),
295             salt => MIME::Base64::decode($salt),
296             hash => MIME::Base64::decode($hash),
297             }
298             } else {
299 0         0 croak "Invalid format";
300             }
301             }
302              
303              
304             sub hasher_from_algorithm {
305 1022     1022 1 1058 my ($self, $algorithm, $args) = @_;
306 1022         3035 my $class = Module::Runtime::use_module("Crypt::PBKDF2::Hash::$algorithm");
307              
308 1022 100       21447 if (defined $args) {
309 21         77 return $class->from_algo_string($args);
310             } else {
311 1001         2794 return $class->new;
312             }
313             }
314              
315              
316             sub clone {
317 1034     1034 1 4508 my ($self, %params) = @_;
318 1034         1244 my $class = ref $self;
319              
320             # If the hasher was built from hash_class and hash_args, then omit it from
321             # the clone. But if it was set by the user, then we need to copy it. We're
322             # assuming that the hasher has no state, so it doesn't need a deep clone.
323             # This is true of all of the ones that I'm shipping, but if it's not true for
324             # you, let me know.
325              
326 1034 50       9817 my %new_args = (
    50          
    50          
    100          
327             $self->has_hash_class ? (hash_class => $self->hash_class) : (),
328             $self->has_hash_args ? (hash_args => $self->hash_args) : (),
329             $self->has_output_len ? (output_len => $self->output_len) : (),
330             $self->has_lazy_hasher ? () : (hasher => $self->hasher),
331             iterations => $self->iterations,
332             salt_len => $self->salt_len,
333             %params,
334             );
335            
336 1034         20531 return $class->new(%new_args);
337             }
338              
339             sub _b64_encode_int32 {
340 511     511   569 my ($self, $value) = @_;
341 511         1569 my $b64 = MIME::Base64::encode(pack("N", $value), "");
342 511         1373 $b64 =~ s/==$//;
343 511         2426 return $b64;
344             }
345              
346             sub _b64_decode_int32 {
347 511     511   477 my ($self, $b64) = @_;
348 511         447 $b64 .= "==";
349 511         3485 return unpack "N", MIME::Base64::decode($b64);
350             }
351              
352             __PACKAGE__->meta->make_immutable;
353             1;
354              
355             __END__
356              
357             =pod
358              
359             =encoding UTF-8
360              
361             =head1 NAME
362              
363             Crypt::PBKDF2 - The PBKDF2 password hashing algorithm.
364              
365             =head1 VERSION
366              
367             version 0.160410
368              
369             =head1 SYNOPSIS
370              
371             use Crypt::PBKDF2;
372              
373             my $pbkdf2 = Crypt::PBKDF2->new(
374             hash_class => 'HMACSHA1', # this is the default
375             iterations => 1000, # so is this
376             output_len => 20, # and this
377             salt_len => 4, # and this.
378             );
379              
380             my $hash = $pbkdf2->generate("s3kr1t_password");
381             if ($pbkdf2->validate($hash, "s3kr1t_password")) {
382             access_granted();
383             }
384              
385             =head1 DESCRIPTION
386              
387             PBKDF2 is a secure password hashing algorithm that uses the techniques of
388             "key strengthening" to make the complexity of a brute-force attack
389             arbitrarily high. PBKDF2 uses any other cryptographic hash or cipher (by
390             convention, usually HMAC-SHA1, but C<Crypt::PBKDF2> is fully pluggable), and
391             allows for an arbitrary number of iterations of the hashing function, and a
392             nearly unlimited output hash size (up to 2**32 - 1 times the size of the
393             output of the backend hash). The hash is salted, as any password hash should
394             be, and the salt may also be of arbitrary size.
395              
396             =head1 ATTRIBUTES
397              
398             =head2 hash_class
399              
400             B<Type:> String, B<Default:> HMACSHA1
401              
402             The name of the default class that will provide PBKDF2's Pseudo-Random
403             Function (the backend hash). If the value starts with a C<+>, the C<+> will
404             be removed and the remainder will be taken as a fully-qualified package
405             name. Otherwise, the value will be appended to C<Crypt::PBKDF2::Hash::>.
406              
407             =head2 hash_args
408              
409             B<Type:> HashRef, B<Default:> {}
410              
411             Arguments to be passed to the C<hash_class> constructor.
412              
413             =head2 hasher
414              
415             B<Type:> Object (must fulfill role L<Crypt::PBKDF2::Hash>), B<Default:> None.
416              
417             It is also possible to provide a hash object directly; in this case the
418             C<hash_class> and C<hash_args> are ignored.
419              
420             =head2 iterations
421              
422             B<Type:> Integer, B<Default:> 1000.
423              
424             The default number of iterations of the hashing function to use for the
425             C<generate> and C<PBKDF2> methods.
426              
427             =head2 output_len
428              
429             B<Type:> Integer.
430              
431             The default size (in bytes, not bits) of the output hash. If a value isn't
432             provided, the output size depends on the C<hash_class>S< / >C<hasher>
433             selected, and will equal the output size of the backend hash (e.g. 20 bytes
434             for HMACSHA1).
435              
436             =head2 salt_len
437              
438             B<Type:> Integer, B<Default:> 4
439              
440             The default salt length (in bytes) for the C<generate> method.
441              
442             =head2 encoding
443              
444             B<Type:> String (either "crypt" or "ldap"), B<Default:> "ldap"
445              
446             The hash format to generate. The "ldap" format is intended to be compatible
447             with RFC2307, and looks like:
448              
449             {X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk=
450              
451             While the "crypt" format is similar to the format used by the C<crypt()>
452             function, except with more structured information in the second (salt) field.
453             It looks like:
454              
455             $PBKDF2$HMACSHA1:1000:4q9OTg==$9Pb6bCRgnct/dga+4v4Lyv8x31s=
456              
457             Versions of this module up to 0.110461 generated the "crypt" format, so set
458             that if you want it. Current versions of this module will read either format,
459             but the "ldap" format is preferred.
460              
461             =head2 length_limit
462              
463             B<Type:> Integer
464              
465             The maximum password length to allow, for generate and verify functions.
466             Allowing passwords of unlimited length can allow a denial-of-service attack
467             in which an attacker asks the server to validate very large passwords.
468              
469             For compatibility this attribute is unset by default, but it is recommended
470             to set it to a reasonably small value like 100 -- large enough that users
471             aren't discouraged from having secure passwords, but small enough to limit
472             the computation needed to validate any one password.
473              
474             =head1 METHODS
475              
476             =head2 generate ($password, [$salt])
477              
478             Generates a hash for the given C<$password>. If C<$salt> is not provided,
479             a random salt with length C<salt_len> will be generated.
480              
481             There are two output formats available, depending on the setting of the
482             C<encoding> attribute: "ldap" and "crypt"; see the documentation for
483             L</encoding> for more information.
484              
485             =head2 validate ($hashed, $password)
486              
487             Validates whether the password C<$password> matches the hash string
488             C<$hashed>. May throw an exception if the format of C<$hashed> is invalid;
489             otherwise, returns true or false. Accepts both formats that the "generate"
490             method can produce.
491              
492             =head2 PBKDF2 ($salt, $password)
493              
494             The raw PBKDF2 algorithm. Given the C<$salt> and C<$password>, returns the
495             raw binary hash.
496              
497             =head2 PBKDF2_base64 ($salt, $password)
498              
499             As the C<PBKDF2> method, only the output is encoded with L<MIME::Base64>.
500              
501             =head2 PBKDF2_hex ($salt, $password)
502              
503             As the C<PBKDF2> method, only the output is encoded in hexadecimal.
504              
505             =head2 encode_string ($salt, $hash)
506              
507             Given a generated salt and hash, hash, generates output in the form generated by
508             C<generate> and accepted by C<validate>. Unlikely to be of much use to anyone
509             else.
510              
511             =head2 decode_string ($hashed)
512              
513             Given a textual hash in the form generated by C<generate>, decodes it and
514             returns a HashRef containing:
515              
516             =over 4
517              
518             =item *
519              
520             C<algorithm>: A string representing the hash algorithm used. See
521             L</hasher_from_algorithm ($algo_str)>.
522              
523             =item *
524              
525             C<iterations>: The number of iterations used.
526              
527             =item *
528              
529             C<salt>: The salt, in raw binary form.
530              
531             =item *
532              
533             C<hash>: The hash, in raw binary form.
534              
535             =back
536              
537             This method is mostly for internal use, but it has been left public as it
538             may come in handy. If the input data is invalid, this method may throw an
539             exception.
540              
541             =head2 hasher_from_algorithm ($algo_str)
542              
543             Attempts to load and instantiate a C<Crypt::PBKDF2::Hash::*> class based on
544             an algorithm string as produced by C<encode_string> / C<generate>.
545              
546             =head2 clone (%params)
547              
548             Create a new object like this one, but with C<%params> changed.
549              
550             =head1 SEE ALSO
551              
552             =over 4
553              
554             =item *
555              
556             B<Wikipedia: PBKDF2>: L<http://en.wikipedia.org/wiki/PBKDF2>
557              
558             =item *
559              
560             B<RFC2898, PKCS#5 version 2.0>: L<http://tools.ietf.org/html/rfc2898>
561              
562             =item *
563              
564             B<RFC2307, Using LDAP as a Network Information Service>:
565             L<http://tools.ietf.org/html/rfc2307>
566              
567             =back
568              
569             =head1 AUTHOR
570              
571             Andrew Rodland <arodland@cpan.org>
572              
573             =head1 COPYRIGHT AND LICENSE
574              
575             This software is copyright (c) 2016 by Andrew Rodland.
576              
577             This is free software; you can redistribute it and/or modify it under
578             the same terms as the Perl 5 programming language system itself.
579              
580             =cut