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   447 use warnings;
  6         11  
  6         179  
5 6     6   28 use strict;
  6         11  
  6         139  
6              
7 6     6   27 use Crypt::Digest qw(digest_data);
  6         11  
  6         221  
8 6     6   31 use File::KDBX::Error;
  6         17  
  6         246  
9 6     6   32 use File::KDBX::Util qw(:class :erase);
  6         18  
  6         676  
10 6     6   40 use Ref::Util qw(is_arrayref);
  6         10  
  6         245  
11 6     6   32 use Scalar::Util qw(blessed);
  6         11  
  6         217  
12 6     6   30 use namespace::clean;
  6         17  
  6         30  
13              
14             extends 'File::KDBX::Key';
15              
16             our $VERSION = '0.906'; # VERSION
17              
18             sub init {
19 46     46 1 71 my $self = shift;
20 46   33     149 my $primitive = shift // throw 'Missing key primitive';
21              
22 46 100       134 my @primitive = grep { defined } is_arrayref($primitive) ? @$primitive : $primitive;
  85         205  
23 46 50       101 @primitive or throw 'Composite key must have at least one component key', count => scalar @primitive;
24              
25 46         75 my @keys = map { blessed $_ && $_->can('raw_key') ? $_ : File::KDBX::Key->new($_,
26 85 100 66     552 keep_primitive => $self->{keep_primitive}) } @primitive;
27 46         113 $self->{keys} = \@keys;
28              
29 46         125 return $self->hide;
30             }
31              
32              
33             sub raw_key {
34 46     46 1 579 my $self = shift;
35 46         66 my $challenge = shift;
36              
37 46 50       60 my @keys = @{$self->keys} or throw 'Cannot generate a raw key from an empty composite key';
  46         84  
38              
39 46         92 my @basic_keys = map { $_->raw_key } grep { !$_->can('challenge') } @keys;
  67         213  
  85         308  
40 46         109 my $response;
41 46 100       137 $response = $self->challenge($challenge, @_) if defined $challenge;
42 46         121 my $cleanup = erase_scoped \@basic_keys, $response;
43              
44 46 100       778 return digest_data('SHA256',
45             @basic_keys,
46             defined $response ? $response : (),
47             );
48             }
49              
50              
51             sub keys {
52 173     173 1 213 my $self = shift;
53 173 50       330 $self->{keys} = shift if @_;
54 173   50     621 return $self->{keys} ||= [];
55             }
56              
57              
58             sub challenge {
59 45     45 1 89 my $self = shift;
60              
61 45 100       64 my @chalresp_keys = grep { $_->can('challenge') } @{$self->keys} or return '';
  81         327  
  45         87  
62              
63 18         37 my @responses = map { $_->challenge(@_) } @chalresp_keys;
  18         56  
64 18         87 my $cleanup = erase_scoped \@responses;
65              
66 18         278 return digest_data('SHA256', @responses);
67             }
68              
69             sub hide {
70 82     82 1 140 my $self = shift;
71 82         109 $_->hide for @{$self->keys};
  82         163  
72 82         436 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__