1 package File
::KDBX
::Key
;
2 # ABSTRACT: A credential that can protect a KDBX file
7 use Devel
::GlobalDestruction
;
10 use File
::KDBX
::Util
qw(erase);
11 use Hash
::Util
::FieldHash
qw(fieldhashes);
13 use Ref
::Util
qw(is_arrayref is_coderef is_hashref is_ref is_scalarref);
14 use Scalar
::Util
qw(blessed openhandle);
17 our $VERSION = '999.999'; # VERSION
19 fieldhashes \
my %SAFE;
23 $key = File
::KDBX
::Key-
>new({ password
=> $password });
24 $key = File
::KDBX
::Key-
>new($password);
26 $key = File
::KDBX
::Key-
>new({ file
=> $filepath });
27 $key = File
::KDBX
::Key-
>new(\
$file);
28 $key = File
::KDBX
::Key-
>new(\
*FILE
);
30 $key = File
::KDBX
::Key-
>new({ composite
=> [...] });
31 $key = File
::KDBX
::Key-
>new([...]); # composite key
33 $key = File
::KDBX
::Key-
>new({ responder
=> \
&responder
});
34 $key = File
::KDBX
::Key-
>new(\
&responder
); # challenge-response key
38 The primitive used to construct the key
is not saved but
is immediately converted to a raw encryption key
(see
41 A L
<File
::KDBX
::Key
::Composite
> is somewhat special
in that it
does retain a reference to its component
keys,
42 and its raw key
is calculated from its components on demand
.
48 my %args = @_ % 2 == 1 ? (primitive
=> shift, @_) : @_;
50 my $primitive = $args{primitive
};
51 delete $args{primitive
} if !$args{keep_primitive
};
52 return $primitive->hide if blessed
$primitive && $primitive->isa($class);
54 my $self = bless \
%args, $class;
55 return $self->init($primitive) if defined $primitive;
60 local ($., $@, $!, $^E, $?);
61 !in_global_destruction
and do { $_[0]->_clear_raw_key; eval { erase \
$_[0]->{primitive
} } }
66 $key = $key->init($primitive);
68 Initialize a L
<File
::KDBX
::Key
> with a new primitive
. Returns itself to allow
method chaining
.
74 my $primitive = shift // throw
'Missing key primitive';
78 if (is_arrayref
($primitive)) {
79 $pkg = __PACKAGE__
.'::Composite';
81 elsif (is_scalarref
($primitive) || openhandle
($primitive)) {
82 $pkg = __PACKAGE__
.'::File';
84 elsif (is_coderef
($primitive)) {
85 $pkg = __PACKAGE__
.'::ChallengeResponse';
87 elsif (!is_ref
($primitive)) {
88 $pkg = __PACKAGE__
.'::Password';
90 elsif (is_hashref
($primitive) && defined $primitive->{composite
}) {
91 $pkg = __PACKAGE__
.'::Composite';
92 $primitive = $primitive->{composite
};
94 elsif (is_hashref
($primitive) && defined $primitive->{password
}) {
95 $pkg = __PACKAGE__
.'::Password';
96 $primitive = $primitive->{password
};
98 elsif (is_hashref
($primitive) && defined $primitive->{file
}) {
99 $pkg = __PACKAGE__
.'::File';
100 $primitive = $primitive->{file
};
102 elsif (is_hashref
($primitive) && defined $primitive->{responder
}) {
103 $pkg = __PACKAGE__
.'::ChallengeResponse';
104 $primitive = $primitive->{responder
};
107 throw
'Invalid key primitive', primitive
=> $primitive;
112 return $self->init($primitive);
119 Reload a key by re-reading the key source
and recalculating the raw key
. Returns itself to allow
method
128 $raw_key = $key->raw_key;
129 $raw_key = $key->raw_key($challenge);
131 Get the raw encryption key
. This
is calculated based on the primitive
(s
). The C
<$challenge> argument
is for
132 challenge-response type
keys and is ignored by other types
.
134 B
<NOTE
:> The raw key
is sensitive information
and so
is memory-protected
while not being accessed
. If you
135 access it
, you should memzero
or L
<File
::KDBX
::Util
/erase
> it
when you
're done.
141 return $self->{raw_key} if !$self->is_hidden;
142 return $self->_safe->peek(\$self->{raw_key});
147 $self->_clear_raw_key;
148 $self->{raw_key} = shift; # after clear
149 $self->_new_safe->add(\$self->{raw_key}); # auto-hide
154 my $safe = $self->_safe;
155 $safe->clear if $safe;
156 erase \$self->{raw_key};
163 Put the raw key in L<File::KDBX/"Memory Protection">. Does nothing if the raw key is already in memory
164 protection. Returns itself to allow method chaining.
170 $self->_new_safe->add(\$self->{raw_key}) if defined $self->{raw_key};
178 Bring the raw key out of memory protection. Does nothing if the raw key is already out of memory protection.
179 Returns itself to allow method chaining.
185 my $safe = $self->_safe;
186 $safe->unlock if $safe;
192 $bool = $key->is_hidden;
194 Get whether or not the key's raw secret
is currently
in memory protection
.
198 sub is_hidden
{ !!$SAFE{$_[0]} }
200 sub _safe
{ $SAFE{$_[0]} }
201 sub _new_safe
{ $SAFE{$_[0]} = File
::KDBX
::Safe-
>new }
208 A master key is one or more credentials that can protect a KDBX database. When you encrypt a database with
209 a master key, you will need the master key to decrypt it. B<Keep your master key safe!> If someone gains
210 access to your master key, they can open your database. If you forget or lose any part of your master key, all
211 data in the database is lost.
213 There are several different types of keys, each implemented as a subclass:
216 * L<File::KDBX::Key::Password> - Password or passphrase, knowledge of a string of characters
217 * L<File::KDBX::Key::File> - Possession of a file ("key file") with a secret.
218 * L<File::KDBX::Key::ChallengeResponse> - Possession of a device that responds correctly when challenged
219 * L<File::KDBX::Key::YubiKey> - Possession of a YubiKey hardware device (a type of challenge-response)
220 * L<File::KDBX::Key::Composite> - One or more keys combined as one
222 A good master key is produced from a high amount of "entropy" (unpredictability). The more entropy the better.
223 Combining multiple keys into a B<Composite> key combines the entropy of each individual key. For example, if
224 you have a weak password and you combine it with other keys, the composite key is stronger than the weak
225 password key by itself. (Of course it's much better to not have any weak components of your master key.)
227 B<COMPATIBILITY NOTE:> Most KeePass implementations are limited in the types and numbers of keys they support.
228 B<Password> keys are pretty much universally supported. B<File> keys are pretty well-supported. Many do not
229 support challenge-response keys. If you are concerned about compatibility, you should stick with one of these
235 * One password and one key file