File Coverage

blib/lib/Password/OWASP/AbstractBase.pm
Criterion Covered Total %
statement 61 67 91.0
branch 18 18 100.0
condition n/a
subroutine 15 17 88.2
pod 6 6 100.0
total 100 108 92.5


line stmt bran cond sub pod time code
1             our $VERSION = '0.005';
2             use Moose::Role;
3 3     3   2210 use namespace::autoclean;
  3         10855  
  3         10  
4 3     3   13071  
  3         17262  
  3         8  
5             # ABSTRACT: Abstract base class to implement OWASP password recommendations
6              
7             use Authen::Passphrase;
8 3     3   143 use Digest::SHA;
  3         6  
  3         47  
9 3     3   782 use Moose::Util::TypeConstraints qw(enum);
  3         4284  
  3         123  
10 3     3   16 use Try::Tiny;
  3         4  
  3         23  
11 3     3   1159  
  3         6  
  3         1645  
12             requires qw(ppr);
13              
14             has cost => (
15             is => 'ro',
16             isa => 'Int',
17             default => 12,
18             );
19              
20             has hashing => (
21             is => 'ro',
22             isa => enum([qw(sha1 sha256 sha512 none sha384 sha224)]),
23             lazy => 1,
24             builder => '_build_hashing_default',
25             );
26              
27             has update_method => (
28             is => 'ro',
29             isa => 'CodeRef',
30             predicate => 'has_update_method',
31             );
32              
33             my $self = shift;
34             my $pass = shift;
35 6     6 1 291 my $ppr = $self->ppr->new(
36 6         11 cost => $self->cost,
37 6         19 salt_random => 1,
38             passphrase => $self->prehash_password($pass),
39             );
40             return $ppr->as_rfc2307;
41             }
42 6         2830814  
43             my $self = shift;
44             my $given = shift;
45             my $want = shift;
46 22     22 1 849855  
47 22         45 my $ok = try {
48 22         40 my $ppr = $self->ppr->from_rfc2307($want);
49             return 1 if $ppr->match($self->prehash_password($given));
50             };
51 22     22   673 return 1 if $ok;
52 15 100       1300 return 1 if $self->check_legacy_password($given, $want);
53 22         172 return 0;
54 22 100       6566067 }
55 19 100       138  
56 7         51 my ($self, $given, $want) = @_;
57              
58             my $ok = try {
59             my $ppr = $self->ppr->from_rfc2307($want);
60 19     19 1 60 return 1 if $ppr->match($self->_prehash_password($given));
61             return 1 if $ppr->match($given);
62             };
63 19     19   621 if ($ok) {
64 12 100       1106 $self->update_password($given);
65 9 100       3373689 return 1;
66 19         151 }
67 19 100       5006394  
68 6         44 $ok = try {
69 6         64 my $ppr = Authen::Passphrase->from_rfc2307($want);
70             return $ppr->match($given);
71             };
72             return 0 unless $ok;
73 13     13   414 $self->update_password($given);
74 8         4340 return 1;
75 13         91 }
76 13 100       311431  
77 6         21 my $self = shift;
78 6         31 warn "DEPRECATION: Please supply a hashing default";
79             return 'sha512';
80             }
81              
82 0     0   0 my $self = shift;
83 0         0 my $pass = shift;
84 0         0  
85             if ($self->hashing eq 'none') {
86             return $pass;
87             }
88 21     21 1 40  
89 21         38 my $sha = Digest::SHA->new($self->hashing);
90             $sha->add($pass);
91 21 100       625 return $sha->b64digest;
92 3         12 }
93              
94             my $self = shift;
95 18         377 my $pass = shift;
96 18         364  
97 18         214 my $sha = Digest::SHA->new('sha512');
98             $sha->add($pass);
99             return $sha->b64digest;
100             }
101 12     12   24  
102 12         20 my $self = shift;
103             warn "DEPRECATION: Please use prehash_password instead";
104 12         74 return $self->prehash_password(@_);
105 12         279 }
106 12         144  
107             my ($self, $given) = @_;
108             return 0 unless $self->has_update_method;
109             $self->update_method->($self->crypt_password($given));
110 0     0 1 0 return 1;
111 0         0 }
112 0         0  
113             1;
114              
115              
116 12     12 1 34 =pod
117 12 100       499  
118 3         15 =encoding UTF-8
119 3         20  
120             =head1 NAME
121              
122             Password::OWASP::AbstractBase - Abstract base class to implement OWASP password recommendations
123              
124             =head1 VERSION
125              
126             version 0.005
127              
128             =head1 SYNOPSIS
129              
130             package Password::OWASP::MyThing;
131             use Moose;
132              
133             with 'Password::OWASP::AbstractBase';
134              
135             use Authen::Passphrase::SomeThing
136              
137             # You need to implement this method
138             sub ppr { 'Authen::Passphrase::SomeThing' }
139              
140             =head1 DESCRIPTION
141              
142             An abstract base class for modules that want to implement OWASP recommendations
143             for password storage.
144              
145             This class implements the following methods and attributes.
146              
147             =head2 ATTRIBUTES
148              
149             =over
150              
151             =item hashing
152              
153             An enumeration of C<none>, C<sha1>, C<sha224>, C<sha256>, C<sha384>, C<sha512>.
154             The latter is the default. This default will change in the future to C<none>,
155             as the new OWASP policy states that prehashing is a security risk. This is
156             used for the L<Password::OWASP::AbstractBase/prehash_password> function.
157              
158             =item update_method
159              
160             A code ref to update the password in your given store. The first argument is
161             the password that needs to be stored. Setting this value will also enable you
162             to update the password via L<Password::OWASP::AbstractBase/update_password>.
163              
164             =back
165              
166             =head1 METHODS
167              
168             =head2 check_legacy_password
169              
170             Check the password against the former password scheme, assuming it isn't a
171             password scheme that is understood by L<Authen::Passphrase> and the password
172             isn't hashed before it was stored.
173              
174             In case the L<Password::OWASP::AbstractBase/update_method> was provided, the
175             password is updated in place.
176              
177             =head2 update_password
178              
179             Update the password if L<Password::OWASP::AbstractBase/update_method> was
180             provided.
181              
182             =head2 prehash_password
183              
184             Hash the password with the given sha. When hashing is set to C<none>, no hashing
185             wil be performed and the password is returned instead of the hash.
186              
187             =head2 hash_password
188              
189             DEPRECATED: This method will be removed in a future release, please use
190             L<Password::OWASP::AbstractBase/prehash_password> instead.
191              
192             =head2 check_password
193              
194             Check the password against the current password scheme
195              
196             =head2 crypt_password
197              
198             Crypt/hash the password for storage
199              
200             =head1 SEE ALSO
201              
202             =head2 OWASP
203              
204             =over
205              
206             =item * L<OWASP cheatsheet for password storage|https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Password_Storage_Cheat_Sheet.md>
207              
208             =item * L<OWASP cheatsheet for authentication storage|https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md>
209              
210             =item * L<Authen::Passphrase>
211              
212             =back
213              
214             =head1 AUTHOR
215              
216             Wesley Schwengle <waterkip@cpan.org>
217              
218             =head1 COPYRIGHT AND LICENSE
219              
220             This software is Copyright (c) 2019 by Wesley Schwengle.
221              
222             This is free software, licensed under:
223              
224             The (three-clause) BSD License
225              
226             =cut