File Coverage

blib/lib/Crypt/Passphrase/SaltedHash.pm
Criterion Covered Total %
statement 32 32 100.0
branch 5 10 50.0
condition 2 3 66.6
subroutine 9 9 100.0
pod 2 3 66.6
total 50 57 87.7


line stmt bran cond sub pod time code
1             package Crypt::Passphrase::SaltedHash;
2              
3 2     2   314073 use v5.6;
  2         5  
4              
5 2     2   6 use strict;
  2         5  
  2         31  
6 2     2   6 use warnings;
  2         2  
  2         84  
7              
8 2     2   688 use parent 'Crypt::Passphrase::Validator';
  2         498  
  2         8  
9              
10 2     2   1749 use Digest 1.19 ();
  2         561  
  2         35  
11 2     2   355 use MIME::Base64 ();
  2         589  
  2         888  
12              
13             our $VERSION = '0.02';
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              
34             sub new {
35 2     2 0 322363 my $class = shift;
36 2         19 return bless {}, $class;
37             }
38              
39             sub accepts_hash {
40 4     4 1 3088 my ( $self, $hash ) = @_;
41 4 50       36 my ( $has_salt, $alg ) = $hash =~ /^\{(S)?(\w+)\}/ or return;
42 4         21 return exists $DIGESTS{ uc $alg };
43             }
44              
45             sub verify_password {
46 4     4 1 8 my ( $self, $password, $hash ) = @_;
47              
48 4 50       27 my ( $has_salt, $alg ) = $hash =~ /^\{(S)?(\w+)\}/ or return;
49 4 50       12 my $meta = $DIGESTS{ uc $alg } or return;
50              
51 4   66     25 my $name = $meta->[1] || $alg;
52 4         10 my $bytes = $meta->[0] / 8;
53 4         19 my $digest = Digest->new($name);
54 4 50       126 my $bin = MIME::Base64::decode_base64( substr( $hash, length($alg) + 2 + ( $has_salt ? 1 : 0 ) ) );
55 4 50       13 my $salt = $has_salt ? substr( $bin, $bytes ) : "";
56 4         29 my $maybe = $digest->add( $password . $salt )->digest;
57              
58 4         20 return $self->secure_compare( $maybe, substr( $bin, 0, $bytes ) );
59             }
60              
61              
62             1;
63              
64             __END__