File Coverage

blib/lib/DBIx/Class/FilterColumn/Encrypt.pm
Criterion Covered Total %
statement 36 36 100.0
branch 4 6 66.6
condition 2 5 40.0
subroutine 8 8 100.0
pod 1 1 100.0
total 51 56 91.0


line stmt bran cond sub pod time code
1             package DBIx::Class::FilterColumn::Encrypt;
2             $DBIx::Class::FilterColumn::Encrypt::VERSION = '0.003';
3 2     2   486137 use strict;
  2         5  
  2         68  
4 2     2   10 use warnings;
  2         5  
  2         129  
5              
6 2     2   11 use parent 'DBIx::Class';
  2         10  
  2         14  
7             __PACKAGE__->load_components(qw/FilterColumn/);
8              
9 2     2   80939 use Crypt::AuthEnc::GCM 0.048;
  2         17523  
  2         201  
10 2     2   1357 use Crypt::SysRandom;
  2         7755  
  2         823  
11              
12             my $format = 'w a16 a16 a*';
13              
14             sub register_column {
15 2     2 1 1552 my ($self, $column, $info, @rest) = @_;
16              
17 2         9 $self->next::method($column, $info, @rest);
18 2 100       727 return unless my $encrypt = $info->{encrypt};
19 1         2 my %keys = %{ $encrypt->{keys} };
  1         4  
20 1   33     32 my $active = $encrypt->{active_key} || (sort { $b <=> $a } keys %keys)[0];
21 1   50     9 my $cipher = $encrypt->{cipher} || 'AES';
22              
23             $self->filter_column(
24             $column => {
25             filter_to_storage => sub {
26 1     1   339095 my (undef, $plaintext) = @_;
27 1         9 my $iv = Crypt::SysRandom::random_bytes(16);
28 1         310 my $encrypter = Crypt::AuthEnc::GCM->new($cipher, $keys{$active}, $iv);
29 1         16 my $ciphertext = $encrypter->encrypt_add($plaintext);
30 1         4 my $tag = $encrypter->encrypt_done;
31 1         41 return pack $format, $active, $iv, $tag, $ciphertext;
32             },
33             filter_from_storage => sub {
34 1     1   48862 my (undef, $raw) = @_;
35 1         8 my ($key_id, $iv, $expected_tag, $ciphertext) = unpack $format, $raw;
36 1 50       8 my $key = $keys{$key_id} or return undef;
37 1         403 my $decrypter = Crypt::AuthEnc::GCM->new($cipher, $key, $iv);
38 1         14 my $plaintext = $decrypter->decrypt_add($ciphertext);
39 1         8 my $received_tag = $decrypter->decrypt_done;
40 1 50       44 return $received_tag eq $expected_tag ? $plaintext : undef;
41             },
42             },
43 1         17 );
44             }
45              
46             1;
47              
48             # ABSTRACT: Transparently encrypt columns in DBIx::Class
49              
50             __END__