File Coverage

lib/Class/Usul/Crypt.pm
Criterion Covered Total %
statement 31 31 100.0
branch n/a
condition n/a
subroutine 13 13 100.0
pod 4 4 100.0
total 48 48 100.0


line stmt bran cond sub pod time code
1             package Class::Usul::Crypt;
2              
3 4     4   1435 use strict;
  4         29  
  4         125  
4 4     4   24 use warnings;
  4         9  
  4         120  
5              
6 4     4   490 use Class::Usul::Constants qw( NUL );
  4         11  
  4         29  
7 4     4   3595 use Class::Usul::Functions qw( create_token is_coderef is_hashref );
  4         19  
  4         48  
8 4     4   8978 use Crypt::CBC;
  4         15802  
  4         186  
9 4     4   47 use English qw( -no_match_vars );
  4         12  
  4         46  
10 4     4   2037 use Exporter 5.57 qw( import );
  4         115  
  4         144  
11 4     4   3098 use MIME::Base64;
  4         2683  
  4         265  
12 4     4   40 use Sys::Hostname;
  4         10  
  4         2611  
13              
14             our @EXPORT_OK = qw( cipher_list decrypt default_cipher encrypt );
15              
16             my $DEFAULT = 'Twofish2'; my $SEED = do { local $RS = undef; <DATA> };
17              
18             # Private functions
19             my $_decode = sub {
20             my $v = $_[ 0 ]; $v =~ tr{ \t}{01}; pack 'b*', $v;
21             };
22              
23             my $_prepare = sub {
24             my $v = $_[ 0 ]; my $pad = " \t" x 8; $v =~ s{^$pad|[^ \t]}{}g; $v;
25             };
26              
27             my $_dref = sub {
28             (is_coderef $_[ 0 ]) ? ($_[ 0 ]->() // NUL) : ($_[ 0 ] // NUL);
29             };
30              
31             my $_eval = sub {
32             my $v = $_prepare->( $_[ 0 ] ); $v ? ((eval $_decode->( $v )) || NUL) : NUL;
33             };
34              
35             my $_cipher_name = sub {
36             (is_hashref $_[ 0 ]) ? $_[ 0 ]->{cipher} || $DEFAULT : $DEFAULT;
37             };
38              
39             my $_compose = sub {
40             $_eval->( $_dref->( $_[ 0 ]->{seed} ) || $SEED ).$_dref->( $_[ 0 ]->{salt} );
41             };
42              
43             my $_new_crypt_cbc = sub {
44             Crypt::CBC->new( -cipher => $_[ 0 ], -key => $_[ 1 ] );
45             };
46              
47             my $_token = sub {
48             create_token( $_compose->( $_[ 0 ] || {} ) );
49             };
50              
51             my $_wards = sub {
52             (is_hashref $_[ 0 ]) || !$_[ 0 ] ? $_token->( $_[ 0 ] ) : $_[ 0 ];
53             };
54              
55             my $_cipher = sub {
56             $_new_crypt_cbc->( $_cipher_name->( $_[ 0 ] ), $_wards->( $_[ 0 ] ) );
57             };
58              
59             # Public functions
60             sub cipher_list () {
61 1     1 1 988 return ( qw( Blowfish Rijndael Twofish2 ) );
62             }
63              
64             sub decrypt (;$$) {
65 5     5 1 8630 return $_cipher->( $_[ 0 ] )->decrypt( decode_base64( $_[ 1 ] ) );
66             }
67              
68             sub default_cipher () {
69 2     2 1 9 return $DEFAULT;
70             }
71              
72             sub encrypt (;$$) {
73 5     5 1 3661 return encode_base64( $_cipher->( $_[ 0 ] )->encrypt( $_[ 1 ] ), NUL );
74             }
75              
76             1;
77              
78             =pod
79              
80             =head1 Name
81              
82             Class::Usul::Crypt - Encryption / decryption functions
83              
84             =head1 Synopsis
85              
86             use Class::Usul::Crypt qw(decrypt encrypt);
87              
88             my $args = q(); # OR
89             my $args = 'salt'; # OR
90             my $args = { salt => 'salt', seed => 'whiten this' };
91              
92             $args->{cipher} = 'Twofish2'; # Optionally
93              
94             my $base64_encrypted_text = encrypt( $args, $plain_text );
95              
96             my $plain_text = decrypt( $args, $base64_encrypted_text );
97              
98             =head1 Description
99              
100             Exports a pair of functions to encrypt / decrypt data. Obfuscates the default
101             encryption key
102              
103             =head1 Configuration and Environment
104              
105             The C<$key> can be a string (including the null string) or a hash reference
106             with I<salt> and I<seed> keys. The I<seed> attribute can be a code reference in
107             which case it will be called with no argument and the return value used
108              
109             Lifted from L<Acme::Bleach> the default seed for the key generator has been
110             whitened and included in this source file
111              
112             The seed is C<eval>'d in string context and then the salt is concatenated onto
113             it before being passed to L<create token|Class::Usul::Functions/create_token>.
114             Uses this value as the key for a L<Crypt::CBC> object
115              
116             =head1 Subroutines/Methods
117              
118             =head2 decrypt
119              
120             my $plain = decrypt( $salt || \%params, $encoded );
121              
122             Decodes and decrypts the C<$encoded> argument and returns the plain
123             text result. See the L</encrypt> method
124              
125             =head2 encrypt
126              
127             my $encoded = encrypt( $salt || \%params, $plain );
128              
129             Encrypts the plain text passed in the C<$plain> argument and returns
130             it Base64 encoded. By default L<Crypt::Twofish2> is used to do the
131             encryption. The optional C<< $params->{cipher} >> attribute overrides this
132              
133             =head2 cipher_list
134              
135             @list_of_ciphers = cipher_list();
136              
137             Returns the list of ciphers supported by L<Crypt::CBC>. These may not
138             all be installed
139              
140             =head2 default_cipher
141              
142             $ciper_name = default_cipher();
143              
144             Returns I<Twofish2>
145              
146             =head1 Diagnostics
147              
148             None
149              
150             =head1 Dependencies
151              
152             =over 3
153              
154             =item L<Crypt::CBC>
155              
156             =item L<Crypt::Twofish2>
157              
158             =item L<Exporter>
159              
160             =item L<MIME::Base64>
161              
162             =back
163              
164             =head1 Incompatibilities
165              
166             There are no known incompatibilities in this module
167              
168             =head1 Bugs and Limitations
169              
170             There are no known bugs in this module.
171             Please report problems to the address below.
172             Patches are welcome
173              
174             =head1 Author
175              
176             Peter Flanigan, C<< <pjfl@cpan.org> >>
177              
178             =head1 License and Copyright
179              
180             Copyright (c) 2017 Peter Flanigan. All rights reserved
181              
182             This program is free software; you can redistribute it and/or modify it
183             under the same terms as Perl itself. See L<perlartistic>
184              
185             This program is distributed in the hope that it will be useful,
186             but WITHOUT WARRANTY; without even the implied warranty of
187             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
188              
189             =cut
190              
191             # Local Variables:
192             # mode: perl
193             # tab-width: 3
194             # End:
195              
196             __DATA__
197            
198            
199            
200            
201            
202            
203            
204            
205            
206            
207            
208            
209            
210            
211            
212            
213