File Coverage

blib/lib/Crypt/Passphrase/Bcrypt.pm
Criterion Covered Total %
statement 39 40 97.5
branch 9 14 64.2
condition 9 14 64.2
subroutine 10 11 90.9
pod 4 6 66.6
total 71 85 83.5


line stmt bran cond sub pod time code
1             package Crypt::Passphrase::Bcrypt;
2             $Crypt::Passphrase::Bcrypt::VERSION = '0.009';
3 3     3   412072 use strict;
  3         7  
  3         121  
4 3     3   14 use warnings;
  3         4  
  3         200  
5              
6 3     3   448 use Crypt::Passphrase 0.010 -encoder;
  3         3731  
  3         16  
7              
8 3     3   5887 use Carp qw/croak carp/;
  3         5  
  3         158  
9 3     3   783 use Crypt::Bcrypt 0.011 qw/bcrypt bcrypt_prehashed bcrypt_check_prehashed bcrypt_needs_rehash bcrypt_supported_prehashes/;
  3         10415  
  3         1582  
10              
11             my %supported_prehash = map { $_ => 1 } bcrypt_supported_prehashes();
12              
13       0 0   sub ignore {
14             }
15              
16             my %checkers = (
17             ignore => \&ignore,
18             warn => \&carp,
19             die => \&croak,
20             );
21              
22             sub new {
23 2     2 0 520 my ($class, %args) = @_;
24 2   50     16 my $subtype = $args{subtype} // '2b';
25 2 50       10 croak "Unknown subtype $subtype" unless $subtype =~ / \A 2 [abxy] \z /x;
26 2   100     8 my $hash = $args{hash} // '';
27 2 50 66     11 croak 'Invalid hash' if length $args{hash} and not $supported_prehash{ $args{hash} };
28              
29 2   50     8 my $check = $args{length_check} // 'die';
30 2 50       7 my $checker = ref $check ? $check : $checkers{$check};
31 2 50       7 croak "Invalid length check value $check" if not defined $checker;
32              
33             return bless {
34 2   50     17 cost => $args{cost} // 14,
35             subtype => $subtype,
36             hash => $hash,
37             checker => $checker,
38             }, $class;
39             }
40              
41             sub hash_password {
42 3     3 1 822227 my ($self, $password) = @_;
43              
44 3 100 66     24 if (!$self->{hash} && $self->{checker} != \&ignore) {
45 2         30 my $length = length $password;
46 2 100       8 if ($length > 72) {
47 1         298 $self->{checker}->("Password is only allowed to be 72 characters, got $length characters");
48             }
49 1 50       3 if ($password =~ /\0/) {
50 0         0 $self->{checker}->("Password is not allowed to contain null characters");
51             }
52             }
53              
54 2         8 my $salt = $self->random_bytes(16);
55 2         55 return bcrypt_prehashed($password, $self->{subtype}, $self->{cost}, $salt, $self->{hash});
56             }
57              
58             sub needs_rehash {
59 5     5 1 5778627 my ($self, $hash) = @_;
60 5         12 return bcrypt_needs_rehash($hash, @{$self}{qw/subtype cost hash/});
  5         31  
61             }
62              
63             sub crypt_subtypes {
64 2     2 1 3344172 return (qw/2a 2b 2x 2y/, map { "bcrypt-$_" } bcrypt_supported_prehashes());
  6         50  
65             }
66              
67             sub verify_password {
68 6     6 1 2865293 my ($class, $password, $hash) = @_;
69 6         33 return bcrypt_check_prehashed($password, $hash);
70             }
71              
72             1;
73              
74             #ABSTRACT: A bcrypt encoder for Crypt::Passphrase
75              
76             __END__