File Coverage

blib/lib/Text/Password/CoreCrypt.pm
Criterion Covered Total %
statement 46 46 100.0
branch 12 18 66.6
condition 21 24 87.5
subroutine 10 10 100.0
pod 4 4 100.0
total 93 102 91.1


line stmt bran cond sub pod time code
1             package Text::Password::CoreCrypt;
2             our $VERSION = "0.43";
3              
4             require 5.008_008;
5 5     5   291349 use autouse 'Carp' => qw(croak carp);
  5         936  
  5         37  
6              
7 5     5   1097 use Moo;
  5         7120  
  5         28  
8 5     5   3372 use strictures 2;
  5         1372  
  5         237  
9              
10 5     5   3344 use Types::Standard qw(Int Bool);
  5         241517  
  5         39  
11 5     5   12163 use constant Min => 4;
  5         14  
  5         757  
12              
13             has default => ( is => 'rw', isa => Int->where('$_ >= 8'), default => sub {8} );
14             has readability => ( is => 'rw', isa => Bool, default => 1 );
15              
16 5     5   37 no Moo::sification;
  5         10  
  5         62  
17              
18             my @w = ( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' );
19             my @seeds = ( @w, '.', '/' );
20             my @ascii = ( @seeds, ' ', '#', ',', qw# ! % & ( ) * + - : ; < = > ? @ [ ] ^ _ ` { | } ~ # ); # ", ' $ and \ are omitted for security reasons
21              
22             =encoding utf-8
23              
24             =head1 NAME
25              
26             Text::Password::CoreCrypt - generate and verify Password with perl CORE::crypt()
27              
28             =head1 SYNOPSIS
29              
30             my $pwd = Text::Password::CoreCrypt->new();
31             my( $raw, $hash ) = $pwd->generate(); # list context is required
32             my $input = $req->body_parameters->{passwd};
33             my $data = $pwd->encrypt($input); # you don't have to care about salt
34              
35             my $flag = $pwd->verify( $input, $data );
36              
37             =head1 DESCRIPTION
38              
39             Text::Password::CoreCrypt is a base module for Text::Password::AutoMigration.
40              
41             B directly.
42              
43             =head2 Constructor and initialization
44              
45             =head3 new()
46              
47             No arguments are required. But you can set some parameters.
48              
49             =over
50              
51              
52             =item default( I )
53              
54              
55             You can set default length with param 'default' like below:
56              
57             $pwd = Text::Password::AutoMiglation->new( default => 12 );
58              
59              
60              
61             =item readablity( I )
62              
63              
64             Or you can set default strength for password with param 'readablity'.
65              
66             It must be a boolean, default is 1.
67              
68             If it was set as 0, you can generate stronger passwords with generate().
69              
70             $pwd = Text::Password::AutoMiglation->new( readability => 0 );
71              
72              
73             =back
74              
75             =head2 Methods and Subroutines
76              
77             =head3 verify( $raw, $hash )
78              
79             returns true if the verification succeeds.
80              
81             =cut
82              
83             sub verify {
84 505     505 1 843648 my $self = shift;
85 505         1317 my ( $input, $data ) = @_;
86 505 50       3072 warn __PACKAGE__, " makes 13 bytes hash strings. Your data must be wrong: ", $data
87             unless $data =~ /^\S[\s!-~]{12}$/;
88 505         9432 return $data eq CORE::crypt( $input, $data );
89             }
90              
91             =head3 nonce( I )
92              
93             generates the random strings with enough strength.
94              
95             the length defaults to 8 || $self->default().
96              
97             =cut
98              
99             sub nonce {
100 233944     233944 1 360625 my $self = shift;
101 233944   66     496313 my $length = shift || $self->default();
102              
103 233944 100 100     914406 croak "Unvalid length for nonce was set" if $length !~ /^\d+$/ or $length < Min;
104              
105 233942         365296 my $n = '';
106              
107 233942   66     312509 do { # redo unless it gets enough strength
      100        
      100        
      100        
      100        
108 397335         836072 $n = $w[ rand @w ];
109 397335         6027516 $n .= $ascii[ rand @ascii ] while length $n < $length;
110             } while $n =~ /^\w+$/ # full of word characters
111             or $n =~ /^\W+$/ # full of non-word characters
112             or $n !~ /\d/ # no numbers
113             or $n !~ /[A-Z]/ # no upper case
114             or $n !~ /[a-z]/ # no lower case
115             or $n =~ /\s+$/; # white spaces at the end
116              
117 233942         11299347 return $n;
118             }
119              
120             =head3 encrypt( I )
121              
122             returns hash with CORE::crypt().
123              
124             salt will be made automatically.
125              
126             =cut
127              
128             sub encrypt {
129 504     504 1 8951 my ( $self, $input ) = @_;
130 504 50       1124 croak __PACKAGE__, " requires at least ", Min, "length" if length $input < Min;
131 504 50       1072 carp __PACKAGE__, " ignores the password with over 8 bytes" if length $input > 8;
132 504 50       1233 croak __PACKAGE__, " doesn't allow any Wide Characters or white spaces" if $input =~ /[^ -~]/;
133              
134 504         11586 return CORE::crypt( $input, $seeds[ rand @seeds ] . $seeds[ rand @seeds ] );
135             }
136              
137             =head3 generate( I )
138              
139             generates pair of new password and its hash.
140              
141             less readable characters(0Oo1Il|!2Zz5sS$6b9qCcKkUuVvWwXx.,:;~-^'"`) are forbidden
142             unless $self->readability is 0.
143              
144             the length defaults to 8 || $self->default().
145              
146             =cut
147              
148             sub generate {
149 1613     1613 1 8376690 my $self = shift;
150 1613   66     62105 my $length = shift || $self->default();
151              
152 1613 50       23367 croak "Invalid length was set" unless $length =~ /^\d+$/;
153 1613 100       6315 croak ref $self, "::generate requires at least ", Min, " length" if $length < Min;
154 1612 50       5046 croak ref $self, "::generate requires list context" unless wantarray;
155              
156 1612         3418 my $raw;
157 1612         3268 do { # redo unless it gets enough readability
158 231622         1509518 do { $raw = $self->nonce($length) } while $raw =~ /^\s?[\$'"]/;
  231622         457158  
159 231622 100       4293257 return $raw, $self->encrypt($raw) unless $self->readability();
160             } while $raw =~ /[0Oo1Il|!2Zz5sS6b9qCcKkUuVvWwXx.,:;~\-^`]/;
161 1111         13534 return $raw, $self->encrypt($raw);
162             }
163              
164             1;
165              
166             __END__