File Coverage

blib/lib/Crypt/Passphrase/Bcrypt/AES.pm
Criterion Covered Total %
statement 47 51 92.1
branch 9 22 40.9
condition 4 11 36.3
subroutine 11 11 100.0
pod 0 4 0.0
total 71 99 71.7


line stmt bran cond sub pod time code
1             package Crypt::Passphrase::Bcrypt::AES;
2              
3 1     1   291498 use 5.014;
  1         5  
4 1     1   7 use warnings;
  1         2  
  1         106  
5              
6             our $VERSION = '0.002';
7              
8 1     1   12 use parent 'Crypt::Passphrase::Bcrypt::Encrypted';
  1         2  
  1         10  
9 1     1   20371 use Crypt::Passphrase 0.019 -encoder;
  1         23  
  1         9  
10              
11 1     1   64 use Carp 'croak';
  1         2  
  1         92  
12 1     1   701 use Crypt::Rijndael 1.16;
  1         693  
  1         123  
13              
14             my %mode = (
15             'aes-cfb' => Crypt::Rijndael::MODE_CFB,
16             'aes-ofb' => Crypt::Rijndael::MODE_OFB,
17             'aes-ctr' => Crypt::Rijndael::MODE_CTR,
18             'aes-ecb-pad' => Crypt::Rijndael::MODE_ECB,
19             'aes-cbc-pad' => Crypt::Rijndael::MODE_CBC,
20             );
21              
22             sub new {
23 1     1 0 21 my ($class, %args) = @_;
24 1 50       6 my $peppers = $args{peppers} or croak('No peppers given');
25 1 50 33 1   9 $args{active} //= (sort {; no warnings 'numeric'; $b <=> $a || $b cmp $a } keys %{ $peppers })[0];
  1         2  
  1         906  
  1         8  
  1         9  
  1         7  
26 1   50     7 my $mode = delete $args{mode} // 'ctr';
27 1         3 my $cipher = "aes-$mode";
28 1 50       4 croak("No such mode $mode") if not exists $mode{$cipher};
29 1         13 my $self = $class->SUPER::new(%args, cipher => $cipher);
30 1         64 for my $key (keys %{$peppers}) {
  1         4  
31 2         35 my $length = length $peppers->{$key};
32 2 0 33     10 croak "Pepper $key has invalid length $length" if $length != 16 && $length != 24 && $length != 32;
      33        
33 2         11 $self->{peppers}{$key} = $peppers->{$key};
34             }
35 1         8 return $self;
36             }
37              
38             sub encrypt_hash {
39 2     2 0 104846 my ($self, $cipher, $id, $iv, $raw) = @_;
40 2 50       11 if ($cipher =~ /-pad$/) {
41 0         0 my $pad_length = 16 - length($raw) % 16;
42 0         0 $raw .= chr($pad_length) x $pad_length;
43             }
44 2 50       12 my $mode = $mode{$cipher} or croak "No such cipher $cipher";
45 2 50       9 my $secret = $self->{peppers}{$id} or croak "No such pepper $id";
46 2         44 return Crypt::Rijndael->new($secret, $mode)->encrypt($raw, $iv);
47             }
48              
49             sub decrypt_hash {
50 3     3 0 322812 my ($self, $cipher, $id, $iv, $raw) = @_;
51 3 50       22 my $mode = $mode{$cipher} or croak "No such cipher $cipher";
52 3 50       17 my $secret = $self->{peppers}{$id} or croak "No such pepper $id";
53 3         60 my $plaintext = Crypt::Rijndael->new($secret, $mode)->decrypt($raw, $iv);
54 3 50       23 if ($cipher =~ /-pad$/) {
55 0         0 my $pad_length = ord substr $plaintext, -1;
56 0 0       0 substr($plaintext, -$pad_length, $pad_length, '') eq chr($pad_length) x $pad_length or croak 'Incorrectly padded';
57             }
58 3         11 return $plaintext;
59             }
60              
61             sub supported_ciphers {
62 1     1 0 1198 return keys %mode;
63             }
64              
65             1;
66              
67             __END__