File Coverage

blib/lib/File/KDBX/Key/Composite.pm
Criterion Covered Total %
statement 59 63 93.6
branch 13 16 81.2
condition 4 8 50.0
subroutine 13 14 92.8
pod 6 6 100.0
total 95 107 88.7


line stmt bran cond sub pod time code
1             package File::KDBX::Key::Composite;
2             # ABSTRACT: A composite key made up of component keys
3              
4 6     6   475 use warnings;
  6         10  
  6         186  
5 6     6   28 use strict;
  6         8  
  6         146  
6              
7 6     6   28 use Crypt::Digest qw(digest_data);
  6         7  
  6         222  
8 6     6   36 use File::KDBX::Error;
  6         10  
  6         272  
9 6     6   43 use File::KDBX::Util qw(:class :erase);
  6         11  
  6         646  
10 6     6   35 use Ref::Util qw(is_arrayref);
  6         16  
  6         237  
11 6     6   37 use Scalar::Util qw(blessed);
  6         12  
  6         225  
12 6     6   34 use namespace::clean;
  6         9  
  6         30  
13              
14             extends 'File::KDBX::Key';
15              
16             our $VERSION = '0.905'; # VERSION
17              
18             sub init {
19 46     46 1 75 my $self = shift;
20 46   33     91 my $primitive = shift // throw 'Missing key primitive';
21              
22 46 100       132 my @primitive = grep { defined } is_arrayref($primitive) ? @$primitive : $primitive;
  85         193  
23 46 50       94 @primitive or throw 'Composite key must have at least one component key', count => scalar @primitive;
24              
25 46         73 my @keys = map { blessed $_ && $_->can('raw_key') ? $_ : File::KDBX::Key->new($_,
26 85 100 66     518 keep_primitive => $self->{keep_primitive}) } @primitive;
27 46         108 $self->{keys} = \@keys;
28              
29 46         102 return $self->hide;
30             }
31              
32              
33             sub raw_key {
34 46     46 1 572 my $self = shift;
35 46         62 my $challenge = shift;
36              
37 46 50       58 my @keys = @{$self->keys} or throw 'Cannot generate a raw key from an empty composite key';
  46         86  
38              
39 46         87 my @basic_keys = map { $_->raw_key } grep { !$_->can('challenge') } @keys;
  67         183  
  85         292  
40 46         80 my $response;
41 46 100       112 $response = $self->challenge($challenge, @_) if defined $challenge;
42 46         112 my $cleanup = erase_scoped \@basic_keys, $response;
43              
44 46 100       720 return digest_data('SHA256',
45             @basic_keys,
46             defined $response ? $response : (),
47             );
48             }
49              
50              
51             sub keys {
52 173     173 1 209 my $self = shift;
53 173 50       301 $self->{keys} = shift if @_;
54 173   50     620 return $self->{keys} ||= [];
55             }
56              
57              
58             sub challenge {
59 45     45 1 65 my $self = shift;
60              
61 45 100       74 my @chalresp_keys = grep { $_->can('challenge') } @{$self->keys} or return '';
  81         305  
  45         90  
62              
63 18         38 my @responses = map { $_->challenge(@_) } @chalresp_keys;
  18         83  
64 18         84 my $cleanup = erase_scoped \@responses;
65              
66 18         278 return digest_data('SHA256', @responses);
67             }
68              
69             sub hide {
70 82     82 1 131 my $self = shift;
71 82         96 $_->hide for @{$self->keys};
  82         163  
72 82         395 return $self;
73             }
74              
75             sub show {
76 0     0 1   my $self = shift;
77 0           $_->show for @{$self->keys};
  0            
78 0           return $self;
79             }
80              
81             1;
82              
83             __END__