File Coverage

blib/lib/Crypt/Passphrase/SaltedHash.pm
Criterion Covered Total %
statement 32 32 100.0
branch 7 10 70.0
condition 2 3 66.6
subroutine 9 9 100.0
pod 2 3 66.6
total 52 57 91.2


line stmt bran cond sub pod time code
1             package Crypt::Passphrase::SaltedHash;
2              
3 2     2   321265 use v5.6;
  2         21  
4              
5 2     2   8 use strict;
  2         3  
  2         31  
6 2     2   13 use warnings;
  2         3  
  2         74  
7              
8 2     2   726 use parent 'Crypt::Passphrase::Validator';
  2         482  
  2         8  
9              
10 2     2   3275 use Digest 1.19 ();
  2         562  
  2         35  
11 2     2   348 use MIME::Base64 ();
  2         603  
  2         657  
12              
13             our $VERSION = '0.03';
14              
15             # ABSTRACT: Validate against Crypt::SaltedHash hashes with Crypt::Passphrase
16              
17              
18             my %DIGESTS = (
19             GOST => [ 256, "GOST" ],
20             HMACMD5 => [ 128, "HMAC-MD5" ], # Note: Digest::HMAC does not work with Crypt::SaltedHash
21             HMACSHA => [ 160, "HMAC-SHA-1" ],
22             MD2 => [128],
23             MD4 => [128],
24             MD5 => [128],
25             MD6 => [256],
26             SHA => [ 160, "SHA-1" ],
27             SHA224 => [ 224, "SHA-224" ],
28             SHA256 => [ 256, "SHA-256" ],
29             SHA384 => [ 384, "SHA-384" ],
30             SHA512 => [ 512, "SHA-512" ],
31             );
32              
33             my $ALGS = join( "|", keys %DIGESTS );
34              
35              
36             sub new {
37 2     2 0 326653 my $class = shift;
38 2         17 return bless {}, $class;
39             }
40              
41             sub accepts_hash {
42 8     8 1 7576 my ( $self, $hash ) = @_;
43 8 50       183 my ( $has_salt, $alg ) = $hash =~ /^\{(S)?(${ALGS})\}/ or return;
44 8         42 return exists $DIGESTS{ uc $alg };
45             }
46              
47             sub verify_password {
48 8     8 1 18 my ( $self, $password, $hash ) = @_;
49              
50 8 50       158 my ( $has_salt, $alg ) = $hash =~ /^\{(S)?(${ALGS})\}/ or return;
51 8 50       25 my $meta = $DIGESTS{ uc $alg } or return;
52              
53 8   66     28 my $name = $meta->[1] || $alg;
54 8         14 my $bytes = $meta->[0] / 8;
55 8         29 my $digest = Digest->new($name);
56 8 100       257 my $bin = MIME::Base64::decode_base64( substr( $hash, length($alg) + 2 + ( $has_salt ? 1 : 0 ) ) );
57 8 100       24 my $salt = $has_salt ? substr( $bin, $bytes ) : "";
58 8         69 my $maybe = $digest->add( $password . $salt )->digest;
59              
60 8         29 return $self->secure_compare( $maybe, substr( $bin, 0, $bytes ) );
61             }
62              
63              
64             1;
65              
66             __END__