File Coverage

blib/lib/Text/Password/CoreCrypt.pm
Criterion Covered Total %
statement 48 48 100.0
branch 12 18 66.6
condition 18 20 90.0
subroutine 9 9 100.0
pod 4 4 100.0
total 91 99 91.9


line stmt bran cond sub pod time code
1             package Text::Password::CoreCrypt;
2             our $VERSION = "0.16";
3              
4             require 5.008_008;
5 5     5   3392 use Carp qw(croak carp);
  5         24  
  5         296  
6              
7 5     5   608 use Moose;
  5         478078  
  5         34  
8 5     5   34914 use Moose::Util::TypeConstraints;
  5         37  
  5         54  
9              
10             has minimum => ( is => 'ro', isa => 'Int', default => 4 );
11              
12             subtype 'Default', as 'Int', where { $_ >= 4 }, message {"The Default must be 4 or higher."};
13             has default => ( is => 'rw', isa => 'Default', default => 8 );
14             has readability => ( is => 'rw', isa => 'Bool', default => 1 );
15              
16             __PACKAGE__->meta->make_immutable;
17 5     5   11932 no Moose;
  5         19  
  5         24  
18              
19             my @ascii = (
20             '!', '#', qw! " $ % & ' ( ) * + !, ',', qw! - . / !,
21              
22             0 .. 9, qw( : ; < = > ? @ ),
23             'A' .. 'Z', qw( [ \ ] ^ _ ` ), # to void syntax highlighting -> `
24             'a' .. 'z', qw( { | } ~ ),
25             );
26              
27             =encoding utf-8
28              
29             =head1 NAME
30              
31             Text::Password::CoreCrypt - generate and verify Password with perl CORE::crypt()
32              
33             =head1 SYNOPSIS
34              
35             my $pwd = Text::Password::CoreCrypt->new();
36             my( $raw, $hash ) = $pwd->genarate(); # list context is required
37             my $input = $req->body_parameters->{passwd};
38             my $data = $pwd->encrypt($input); # salt is made automatically
39             my $flag = $pwd->verify( $input, $data );
40              
41             =head1 DESCRIPTION
42              
43             Text::Password::CoreCrypt is base module for Text::Password::AutoMigration.
44              
45             B<DON'T USE> directly.
46              
47             =head2 Constructor and initialization
48              
49             =head3 new()
50              
51             No arguments are required. But you can set some parameters.
52              
53             =over
54              
55             =item default
56              
57             You can set default length with param 'default' like below:
58              
59             $pwd = Text::Pasword::AutoMiglation->new( default => 12 );
60              
61             =item readablity
62              
63             Or you can set default strength for password with param 'readablity'.
64              
65             It must be a boolean, default is 1.
66              
67             If it was set as 0, you can generate stronger passwords with generate().
68              
69             $pwd = Text::Pasword::AutoMiglation->new( readability => 0 );
70              
71             =back
72              
73             =head2 Methods and Subroutines
74              
75             =head3 verify( $raw, $hash )
76              
77             returns true if the verification succeeds.
78              
79             =cut
80              
81             sub verify {
82 105     105 1 4074 my $self = shift;
83 105         192 my ( $input, $data ) = @_;
84 105 50       304 warn "CORE::crypt makes 13bytes hash strings. Your data must be wrong: $data"
85             if $data !~ /^[ !-~]{13}$/;
86              
87 105         1926 return $data eq CORE::crypt( $input, $data );
88             }
89              
90             =head3 nonce($length)
91              
92             generates the random strings with enough strength.
93              
94             the length defaults to 8($self->default).
95              
96             =cut
97              
98             sub nonce {
99 7804     7804 1 28675 my $self = shift;
100 7804   100     15328 my $length = shift || 8;
101 7804 100 100     28833 croak "Unvalid length for nonce was set" unless $length =~ /^\d+$/ and $length >= 4;
102              
103 7802         12138 my $n = '';
104 7802         62201 my @w = ( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' );
105 7802   66     11010 do { # redo unless it gets enough strength
      100        
      100        
      100        
106 13435         29720 $n = $w[ rand @w ];
107 13435         179536 $n .= $ascii[ rand @ascii ] until length $n >= $length;
108             } while $n =~ /^\w+$/ or $n =~ /^\W+$/ or $n !~ /\d/ or $n !~ /[A-Z]/ or $n !~ /[a-z]/;
109 7802         37686 return $n;
110             }
111              
112             =head3 encrypt($raw)
113              
114             returns hash with CORE::crypt().
115              
116             salt will be made automatically.
117              
118             =cut
119              
120             sub encrypt {
121 5     5 1 18 my $self = shift;
122 5         13 my $input = shift;
123 5         158 my $min = $self->minimum();
124 5 50       28 carp __PACKAGE__ . " requires at least $min length" if length $input < $min;
125 5 50       27 carp __PACKAGE__ . " ignores the password with over 8 bytes" if length $input > 8;
126 5 50       21 carp __PACKAGE__ . " doesn't allow any Wide Characters or white spaces\n" if $input =~ /[^ -~]/;
127              
128 5         19 return CORE::crypt( $input, $self->_salt() );
129             }
130              
131             =head3 generate($length)
132              
133             genarates pair of new password and it's hash.
134              
135             less readable characters(0Oo1Il|!2Zz5sS$6b9qCcKkUuVvWwXx.,:;~-^'"`) are forbidden
136             unless $self->readability is 0.
137              
138             the length defaults to 8($self->default).
139              
140             =cut
141              
142             sub generate {
143 12     12 1 25549 my $self = shift;
144 12   66     463 my $length = shift || $self->default();
145 12         403 my $min = $self->minimum();
146              
147 12 50       82 croak "unvalid length was set" unless $length =~ /^\d+$/;
148 12 50       40 croak ref($self) . "::generate requires list context" unless wantarray;
149 12 100       233 croak ref($self) . "::generate requires at least $min length" if $length < $min;
150              
151 11         24 my $raw;
152 11         18 do { # redo unless it gets enough readability
153 7462         16779 $raw = $self->nonce($length);
154 7462 100       228532 return $raw, $self->encrypt($raw) unless $self->readability();
155             } while ( $raw =~ /[0Oo1Il|!2Zz5sS\$6b9qCcKkUuVvWwXx.,:;~\-^'"`]/i );
156              
157 10         95 return $raw, $self->encrypt($raw);
158             }
159              
160             sub _salt {
161 5     5   8 my $self = shift;
162 5         50 my @seeds = ( 'a' .. 'z', 'A' .. 'Z', 0 .. 9, '.', '/' );
163 5         11 my $salt = '';
164 5         28 $salt .= $seeds[ rand @seeds ] until length $salt == 2;
165 5         1313 return $salt;
166             }
167              
168             1;
169              
170             __END__
171              
172             =head1 LICENSE
173              
174             Copyright (C) Yuki Yoshida(worthmine).
175              
176             This library is free software; you can redistribute it and/or modify
177             it under the same terms as Perl itself.
178              
179             =head1 AUTHOR
180              
181             Yuki Yoshida(worthmine) E<lt>worthmine!at!gmail.comE<gt>