2 # ABSTRACT: Encrypted database to store secret text and files
8 use Crypt
::Digest
qw(digest_data);
9 use Crypt
::PRNG
qw(random_bytes);
10 use Devel
::GlobalDestruction
;
11 use File
::KDBX
::Constants
qw(:all :icon);
12 use File
::KDBX
::Error
;
14 use File
::KDBX
::Util
qw(:class :coercion :empty :search :uuid erase simple_expression_query snakify);
15 use Hash
::Util
::FieldHash
qw(fieldhashes);
16 use List
::Util
qw(any first);
17 use Ref
::Util
qw(is_ref is_arrayref is_plain_hashref);
18 use Scalar
::Util
qw(blessed);
23 our $VERSION = '999.999'; # VERSION
26 fieldhashes \
my (%SAFE, %KEYS);
30 $kdbx = File
::KDBX-
>new(%attributes);
31 $kdbx = File
::KDBX-
>new($kdbx); # copy constructor
33 Construct a new L
<File
::KDBX
>.
41 return $_[0]->clone if @_ == 1 && blessed
$_[0] && $_[0]->isa($class);
44 $data = shift if is_plain_hashref
($_[0]);
46 my $self = bless $data // {}, $class;
48 $self->_set_nonlazy_attributes if !$data;
52 sub DESTROY
{ local ($., $@, $!, $^E, $?); !in_global_destruction
and $_[0]->reset }
56 $kdbx = $kdbx->init(%attributes);
58 Initialize a L
<File
::KDBX
> with a set of attributes
. Returns itself to allow
method chaining
.
60 This
is called by L
</new
>.
68 @$self{keys %args} = values %args;
77 Set a L
<File
::KDBX
> to an empty
state, ready to load a KDBX file
or build a new one
. Returns itself to allow
84 erase
$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY
};
85 erase
$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY
};
94 $kdbx_copy = $kdbx->clone;
95 $kdbx_copy = File
::KDBX-
>new($kdbx);
97 Clone a L
<File
::KDBX
>. The clone will be an exact copy
and completely independent of the original
.
104 return Storable
::dclone
($self);
107 sub STORABLE_freeze
{
113 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
124 @$self{keys %$clone} = values %$clone;
126 $SAFE{$self} = $safe;
128 # Dualvars aren't cloned as dualvars, so coerce the compression flags.
129 $self->compression_flags($self->compression_flags);
131 $self->objects(history
=> 1)->each(sub { $_->kdbx($self) });
134 ##############################################################################
144 $kdbx = KDBX
::File-
>load(\
$string, $key);
145 $kdbx = KDBX
::File-
>load(*IO
, $key);
146 $kdbx = KDBX
::File-
>load($filepath, $key);
147 $kdbx->load(...); # also instance method
149 $kdbx = File
::KDBX-
>load_string($string, $key);
150 $kdbx = File
::KDBX-
>load_string(\
$string, $key);
151 $kdbx->load_string(...); # also instance method
153 $kdbx = File
::KDBX-
>load_file($filepath, $key);
154 $kdbx->load_file(...); # also instance method
156 $kdbx = File
::KDBX-
>load_handle($fh, $key);
157 $kdbx = File
::KDBX-
>load_handle(*IO
, $key);
158 $kdbx->load_handle(...); # also instance method
160 Load a KDBX file from a string buffer
, IO handle
or file from a filesystem
.
162 L
<File
::KDBX
::Loader
> does the heavy lifting
.
166 sub load
{ shift-
>_loader->load(@_) }
167 sub load_string
{ shift-
>_loader->load_string(@_) }
168 sub load_file
{ shift-
>_loader->load_file(@_) }
169 sub load_handle
{ shift-
>_loader->load_handle(@_) }
173 $self = $self->new if !ref $self;
174 require File
::KDBX
::Loader
;
175 File
::KDBX
::Loader-
>new(kdbx
=> $self);
186 $kdbx->dump(\
$string, $key);
187 $kdbx->dump(*IO
, $key);
188 $kdbx->dump($filepath, $key);
190 $kdbx->dump_string(\
$string, $key);
191 \
$string = $kdbx->dump_string($key);
193 $kdbx->dump_file($filepath, $key);
195 $kdbx->dump_handle($fh, $key);
196 $kdbx->dump_handle(*IO
, $key);
198 Dump a KDBX file to a string buffer
, IO handle
or file
in a filesystem
.
200 L
<File
::KDBX
::Dumper
> does the heavy lifting
.
204 sub dump { shift-
>_dumper->dump(@_) }
205 sub dump_string
{ shift-
>_dumper->dump_string(@_) }
206 sub dump_file
{ shift-
>_dumper->dump_file(@_) }
207 sub dump_handle
{ shift-
>_dumper->dump_handle(@_) }
211 $self = $self->new if !ref $self;
212 require File
::KDBX
::Dumper
;
213 File
::KDBX
::Dumper-
>new(kdbx
=> $self);
216 ##############################################################################
218 =method user_agent_string
220 $string = $kdbx->user_agent_string;
222 Get a text string identifying the database client software
.
226 sub user_agent_string
{
228 sprintf('%s/%s (%s/%s; %s/%s; %s)',
229 __PACKAGE__
, $VERSION, @Config::Config
{qw(package version osname osvers archname)});
232 has sig1
=> KDBX_SIG1
, coerce
=> \
&to_number
;
233 has sig2
=> KDBX_SIG2_2
, coerce
=> \
&to_number
;
234 has version
=> KDBX_VERSION_3_1
, coerce
=> \
&to_number
;
236 has inner_headers
=> {};
239 has deleted_objects
=> {};
240 has raw
=> coerce
=> \
&to_string
;
243 has 'headers.comment' => '', coerce
=> \
&to_string
;
244 has 'headers.cipher_id' => sub { $_[0]->version < KDBX_VERSION_4_0
? CIPHER_UUID_AES256
: CIPHER_UUID_CHACHA20
},
246 has 'headers.compression_flags' => COMPRESSION_GZIP
, coerce
=> \
&to_compression_constant
;
247 has 'headers.master_seed' => sub { random_bytes
(32) }, coerce
=> \
&to_string
;
248 has 'headers.encryption_iv' => sub { random_bytes
($_[0]->version < KDBX_VERSION_4_0
? 16 : 12) },
249 coerce
=> \
&to_string
;
250 has 'headers.stream_start_bytes' => sub { random_bytes
(32) }, coerce
=> \
&to_string
;
251 has 'headers.kdf_parameters' => sub {
253 KDF_PARAM_UUID
() => KDF_UUID_AES
,
254 KDF_PARAM_AES_ROUNDS
() => $_[0]->headers->{+HEADER_TRANSFORM_ROUNDS
} // KDF_DEFAULT_AES_ROUNDS
,
255 KDF_PARAM_AES_SEED
() => $_[0]->headers->{+HEADER_TRANSFORM_SEED
} // random_bytes
(32),
258 # has 'headers.transform_seed' => sub { random_bytes(32) };
259 # has 'headers.transform_rounds' => 100_000;
260 # has 'headers.inner_random_stream_key' => sub { random_bytes(32) }; # 64 ?
261 # has 'headers.inner_random_stream_id' => STREAM_ID_CHACHA20;
262 # has 'headers.public_custom_data' => {};
265 has 'meta.generator' => '', coerce
=> \
&to_string
;
266 has 'meta.header_hash' => '', coerce
=> \
&to_string
;
267 has 'meta.database_name' => '', coerce
=> \
&to_string
;
268 has 'meta.database_name_changed' => sub { gmtime }, coerce
=> \
&to_time
;
269 has 'meta.database_description' => '', coerce
=> \
&to_string
;
270 has 'meta.database_description_changed' => sub { gmtime }, coerce
=> \
&to_time
;
271 has 'meta.default_username' => '', coerce
=> \
&to_string
;
272 has 'meta.default_username_changed' => sub { gmtime }, coerce
=> \
&to_time
;
273 has 'meta.maintenance_history_days' => HISTORY_DEFAULT_MAX_AGE
, coerce
=> \
&to_number
;
274 has 'meta.color' => '', coerce
=> \
&to_string
;
275 has 'meta.master_key_changed' => sub { gmtime }, coerce
=> \
&to_time
;
276 has 'meta.master_key_change_rec' => -1, coerce
=> \
&to_number
;
277 has 'meta.master_key_change_force' => -1, coerce
=> \
&to_number
;
278 # has 'meta.memory_protection' => {};
279 has 'meta.custom_icons' => [];
280 has 'meta.recycle_bin_enabled' => true
, coerce
=> \
&to_bool
;
281 has 'meta.recycle_bin_uuid' => UUID_NULL
, coerce
=> \
&to_uuid
;
282 has 'meta.recycle_bin_changed' => sub { gmtime }, coerce
=> \
&to_time
;
283 has 'meta.entry_templates_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
284 has 'meta.entry_templates_group_changed' => sub { gmtime }, coerce
=> \
&to_time
;
285 has 'meta.last_selected_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
286 has 'meta.last_top_visible_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
287 has 'meta.history_max_items' => HISTORY_DEFAULT_MAX_ITEMS
, coerce
=> \
&to_number
;
288 has 'meta.history_max_size' => HISTORY_DEFAULT_MAX_SIZE
, coerce
=> \
&to_number
;
289 has 'meta.settings_changed' => sub { gmtime }, coerce
=> \
&to_time
;
290 # has 'meta.binaries' => {};
291 # has 'meta.custom_data' => {};
293 has 'memory_protection.protect_title' => false
, coerce
=> \
&to_bool
;
294 has 'memory_protection.protect_username' => false
, coerce
=> \
&to_bool
;
295 has 'memory_protection.protect_password' => true
, coerce
=> \
&to_bool
;
296 has 'memory_protection.protect_url' => false
, coerce
=> \
&to_bool
;
297 has 'memory_protection.protect_notes' => false
, coerce
=> \
&to_bool
;
298 # has 'memory_protection.auto_enable_visual_hiding' => false;
301 HEADER_TRANSFORM_SEED
,
302 HEADER_TRANSFORM_ROUNDS
,
303 HEADER_INNER_RANDOM_STREAM_KEY
,
304 HEADER_INNER_RANDOM_STREAM_ID
,
305 HEADER_PUBLIC_CUSTOM_DATA
,
307 sub _set_nonlazy_attributes
{
309 $self->$_ for list_attributes
(ref $self), @ATTRS;
312 =method memory_protection
314 \
%settings = $kdbx->memory_protection
315 $kdbx->memory_protection(\
%settings);
317 $bool = $kdbx->memory_protection($string_key);
318 $kdbx->memory_protection($string_key => $bool);
320 Get
or set memory protection settings
. This globally
(for the whole database
) configures whether
and which of
321 the standard strings should be memory-protected
. The
default setting
is to memory-protect only I
<Password
>
324 Memory protection can be toggled individually
for each entry string
, and individual settings
take precedence
325 over these global settings
.
329 sub memory_protection
{
331 $self->{meta
}{memory_protection
} = shift if @_ == 1 && is_plain_hashref
($_[0]);
332 return $self->{meta
}{memory_protection
} //= {} if !@_;
334 my $string_key = shift;
335 my $key = 'protect_' . lc($string_key);
337 $self->meta->{memory_protection
}{$key} = shift if @_;
338 $self->meta->{memory_protection
}{$key};
341 =method minimum_version
343 $version = $kdbx->minimum_version;
345 Determine the minimum file version required to save a database losslessly
. Using certain databases features
346 might increase this value
. For example
, setting the KDF to Argon2 will increase the minimum version to at
347 least C
<KDBX_VERSION_4_0
> (i
.e
. C
<0x00040000>) because Argon2 was introduced with KDBX4
.
349 This
method never returns less than C
<KDBX_VERSION_3_1
> (i
.e
. C
<0x00030001>). That file version
is so
350 ubiquitous
and well-supported
, there are seldom reasons to
dump in a lesser format nowadays
.
352 B
<WARNING
:> If you
dump a database with a minimum version higher than the current L
</version
>, the dumper will
353 typically issue a warning
and automatically upgrade the database
. This seems like the safest behavior
in order
354 to avoid data loss
, but lower versions have the benefit of being compatible with more software
. It
is possible
355 to prevent auto-upgrades by explicitly telling the dumper which version to
use, but you
do run the risk of
356 data loss
. A database will never be automatically downgraded
.
360 sub minimum_version
{
363 return KDBX_VERSION_4_1
if any
{
364 nonempty
$_->{last_modification_time
}
365 } values %{$self->custom_data};
367 return KDBX_VERSION_4_1
if any
{
368 nonempty
$_->{name
} || nonempty
$_->{last_modification_time
}
369 } @{$self->custom_icons};
371 return KDBX_VERSION_4_1
if $self->groups->next(sub {
372 nonempty
$_->previous_parent_group ||
374 (any
{ nonempty
$_->{last_modification_time
} } values %{$_->custom_data})
377 return KDBX_VERSION_4_1
if $self->entries(history
=> 1)->next(sub {
378 nonempty
$_->previous_parent_group ||
379 (defined $_->quality_check && !$_->quality_check) ||
380 (any
{ nonempty
$_->{last_modification_time
} } values %{$_->custom_data})
383 return KDBX_VERSION_4_0
if $self->kdf->uuid ne KDF_UUID_AES
;
385 return KDBX_VERSION_4_0
if nonempty
$self->public_custom_data;
387 return KDBX_VERSION_4_0
if $self->objects->next(sub {
388 nonempty
$_->custom_data
391 return KDBX_VERSION_3_1
;
394 ##############################################################################
398 $group = $kdbx->root;
401 Get
or set a database
's root group. You don't necessarily need to explicitly create
or set a root group
402 because it autovivifies
when adding entries
and groups to the database
.
404 Every database
has only a single root group at a
time. Some old KDB files might have multiple root groups
.
405 When reading such files
, a single implicit root group
is created to contain the actual root groups
. When
406 writing to such a format
, if the root group looks like it was implicitly created then it won
't be written and
407 the resulting file might have multiple root groups, as it was before loading. This allows working with older
408 files without changing their written internal structure while still adhering to modern semantics while the
411 The root group of a KDBX database contains all of the database's entries
and other groups
. If you replace the
412 root group
, you are essentially replacing the entire database contents with something
else.
419 $self->{root
} = $self->_wrap_group(@_);
420 $self->{root
}->kdbx($self);
422 $self->{root
} //= $self->_implicit_root;
423 return $self->_wrap_group($self->{root
});
426 # Called by File::KeePass::KDBX so that a File::KDBX an be treated as a File::KDBX::Group in that both types
427 # can have subgroups. File::KDBX already has a `groups' method that does something different from the
428 # File::KDBX::Groups `groups' method.
431 return [] if !$self->{root
};
432 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
435 sub _has_implicit_root
{
437 my $root = $self->root;
438 my $temp = __PACKAGE__-
>_implicit_root;
439 # If an implicit root group has been changed in any significant way, it is no longer implicit.
440 return $root->name eq $temp->name &&
441 $root->is_expanded ^ $temp->is_expanded &&
442 $root->notes eq $temp->notes &&
443 !@{$root->entries} &&
444 !defined $root->custom_icon_uuid &&
445 !keys %{$root->custom_data} &&
446 $root->icon_id == $temp->icon_id &&
447 $root->expires ^ $temp->expires &&
448 $root->default_auto_type_sequence eq $temp->default_auto_type_sequence &&
449 !defined $root->enable_auto_type &&
450 !defined $root->enable_searching;
455 require File
::KDBX
::Group
;
456 return File
::KDBX
::Group-
>new(
459 notes
=> 'Added as an implicit root group by '.__PACKAGE__
.'.',
460 ref $self ? (kdbx
=> $self) : (),
464 =method trace_lineage
466 \
@lineage = $kdbx->trace_lineage($group);
467 \
@lineage = $kdbx->trace_lineage($group, $base_group);
468 \
@lineage = $kdbx->trace_lineage($entry);
469 \
@lineage = $kdbx->trace_lineage($entry, $base_group);
471 Get the direct line of ancestors from C
<$base_group> (default: the root group
) to a group
or entry
. The
472 lineage includes the base group but I
<not> the target group
or entry
. Returns C
<undef> if the target
is not in
473 the database structure
.
480 return $object->lineage(@_);
488 push @lineage, $self->root if !@lineage;
489 my $base = $lineage[-1] or return [];
491 my $uuid = $object->uuid;
492 return \
@lineage if any
{ $_->uuid eq $uuid } @{$base->groups}, @{$base->entries};
494 for my $subgroup (@{$base->groups}) {
495 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
496 return $result if $result;
502 $group = $kdbx->recycle_bin;
503 $kdbx->recycle_bin($group);
505 Get
or set the recycle bin group
. Returns C
<undef> if there
is no recycle bin
and L
</recycle_bin_enabled
> is
506 false
, otherwise the current recycle bin
or an autovivified recycle bin group
is returned
.
512 if (my $group = shift) {
513 $self->recycle_bin_uuid($group->uuid);
517 my $uuid = $self->recycle_bin_uuid;
518 $group = $self->groups->grep(uuid
=> $uuid)->next if $uuid ne UUID_NULL
;
519 if (!$group && $self->recycle_bin_enabled) {
520 $group = $self->add_group(
521 name
=> 'Recycle Bin',
522 icon_id
=> ICON_TRASHCAN_FULL
,
523 enable_auto_type
=> false
,
524 enable_searching
=> false
,
526 $self->recycle_bin_uuid($group->uuid);
531 =method entry_templates
533 $group = $kdbx->entry_templates;
534 $kdbx->entry_templates($group);
536 Get
or set the entry templates group
. May
return C
<undef> if unset
.
540 sub entry_templates
{
542 if (my $group = shift) {
543 $self->entry_templates_group($group->uuid);
546 my $uuid = $self->entry_templates_group;
547 return if $uuid eq UUID_NULL
;
548 return $self->groups->grep(uuid
=> $uuid)->next;
551 =method last_selected
553 $group = $kdbx->last_selected;
554 $kdbx->last_selected($group);
556 Get
or set the
last selected group
. May
return C
<undef> if unset
.
562 if (my $group = shift) {
563 $self->last_selected_group($group->uuid);
566 my $uuid = $self->last_selected_group;
567 return if $uuid eq UUID_NULL
;
568 return $self->groups->grep(uuid
=> $uuid)->next;
571 =method last_top_visible
573 $group = $kdbx->last_top_visible;
574 $kdbx->last_top_visible($group);
576 Get
or set the
last top visible group
. May
return C
<undef> if unset
.
580 sub last_top_visible
{
582 if (my $group = shift) {
583 $self->last_top_visible_group($group->uuid);
586 my $uuid = $self->last_top_visible_group;
587 return if $uuid eq UUID_NULL
;
588 return $self->groups->grep(uuid
=> $uuid)->next;
591 ##############################################################################
595 $kdbx->add_group($group);
596 $kdbx->add_group(%group_attributes, %options);
598 Add a group to a database
. This
is equivalent to identifying a parent group
and calling
599 L
<File
::KDBX
::Group
/add_group
> on the parent group
, forwarding the arguments
. Available options
:
602 * C<group> - Group object or group UUID to add the group to (default: root group)
608 my $group = @_ % 2 == 1 ? shift : undef;
611 # find the right group to add the group to
612 my $parent = delete $args{group
} // $self->root;
613 $parent = $self->groups->grep({uuid
=> $parent})->next if !ref $parent;
614 $parent or throw
'Invalid group';
616 return $parent->add_group(defined $group ? $group : (), %args, kdbx
=> $self);
622 require File
::KDBX
::Group
;
623 return File
::KDBX
::Group-
>wrap($group, $self);
628 \
&iterator
= $kdbx->groups(%options);
629 \
&iterator
= $kdbx->groups($base_group, %options);
631 Get an L
<File
::KDBX
::Iterator
> over I
<groups
> within a database
. Options
:
634 * C<base> - Only include groups within a base group (same as C<$base_group>) (default: L</root>)
635 * C<inclusive> - Include the base group in the results (default: true)
636 * C<algorithm> - Search algorithm, one of C<ids>, C<bfs> or C<dfs> (default: C<ids>)
642 my %args = @_ % 2 == 0 ? @_ : (base
=> shift, @_);
643 my $base = delete $args{base
} // $self->root;
645 return $base->all_groups(%args);
648 ##############################################################################
652 $kdbx->add_entry($entry, %options);
653 $kdbx->add_entry(%entry_attributes, %options);
655 Add an entry to a database
. This
is equivalent to identifying a parent group
and calling
656 L
<File
::KDBX
::Group
/add_entry
> on the parent group
, forwarding the arguments
. Available options
:
659 * C<group> - Group object or group UUID to add the entry to (default: root group)
665 my $entry = @_ % 2 == 1 ? shift : undef;
668 # find the right group to add the entry to
669 my $parent = delete $args{group
} // $self->root;
670 $parent = $self->groups->grep({uuid
=> $parent})->next if !ref $parent;
671 $parent or throw
'Invalid group';
673 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx
=> $self);
679 require File
::KDBX
::Entry
;
680 return File
::KDBX
::Entry-
>wrap($entry, $self);
685 \
&iterator
= $kdbx->entries(%options);
686 \
&iterator
= $kdbx->entries($base_group, %options);
688 Get an L
<File
::KDBX
::Iterator
> over I
<entries
> within a database
. Supports the same options as L
</groups
>,
692 * C<auto_type> - Only include entries with auto-type enabled (default: false, include all)
693 * C<searching> - Only include entries within groups with searching enabled (default: false, include all)
694 * C<history> - Also include historical entries (default: false, include only current entries)
700 my %args = @_ % 2 == 0 ? @_ : (base
=> shift, @_);
701 my $base = delete $args{base
} // $self->root;
703 return $base->all_entries(%args);
706 ##############################################################################
710 \
&iterator
= $kdbx->objects(%options);
711 \
&iterator
= $kdbx->objects($base_group, %options);
713 Get an L
<File
::KDBX
::Iterator
> over I
<objects
> within a database
. Groups
and entries are considered objects
,
714 so this
is essentially a combination of L
</groups> and L</entries
>. This won
't often be useful, but it can be
715 convenient for maintenance tasks. This method takes the same options as L</groups> and L</entries>.
721 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
722 my $base = delete $args{base} // $self->root;
724 return $base->all_objects(%args);
727 sub __iter__ { $_[0]->objects }
729 ##############################################################################
733 \%icon = $kdbx->custom_icon($uuid);
734 $kdbx->custom_icon($uuid => \%icon);
735 $kdbx->custom_icon(%icon);
736 $kdbx->custom_icon(uuid => $value, %icon);
738 Get or set custom icons.
744 my %args = @_ == 2 ? (uuid => shift, data => shift)
745 : @_ % 2 == 1 ? (uuid => shift, @_) : @_;
747 if (!$args{uuid} && !$args{data}) {
748 my %standard = (uuid => 1, data => 1, name => 1, last_modification_time => 1);
749 my @other_keys = grep { !$standard{$_} } keys %args;
750 if (@other_keys == 1) {
751 my $key = $args{key} = $other_keys[0];
752 $args{data} = delete $args{$key};
756 my $uuid = $args{uuid} or throw 'Must provide a custom icon UUID to access
';
757 my $icon = (first { $_->{uuid} eq $uuid } @{$self->custom_icons}) // do {
758 push @{$self->custom_icons}, my $i = { uuid => $uuid };
763 $fields = $args{data} if is_plain_hashref($args{data});
765 while (my ($field, $value) = each %$fields) {
766 $icon->{$field} = $value;
771 =method custom_icon_data
773 $image_data = $kdbx->custom_icon_data($uuid);
775 Get a custom icon image data.
779 sub custom_icon_data {
781 my $uuid = shift // return;
782 my $icon = first { $_->{uuid} eq $uuid } @{$self->custom_icons} or return;
783 return $icon->{data};
786 =method add_custom_icon
788 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
789 $uuid = $kdbx->add_custom_icon(%attributes);
791 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
794 * C<uuid> - Icon UUID (default: autogenerated)
795 * C<data> - Image data (same as C<$image_data>)
796 * C<name> - Name of the icon (text, KDBX4.1+)
797 * C<last_modification_time> - Just what it says (datetime, KDBX4.1+)
801 sub add_custom_icon {
803 my %args = @_ % 2 == 1 ? (data => shift, @_) : @_;
805 defined $args{data} or throw 'Must provide image data
';
807 my $uuid = $args{uuid} // generate_uuid;
808 push @{$self->custom_icons}, {
816 =method remove_custom_icon
818 $kdbx->remove_custom_icon($uuid);
820 Remove a custom icon.
824 sub remove_custom_icon {
828 @{$self->custom_icons} = grep { $_->{uuid} eq $uuid ? do { push @deleted, $_; 0 } : 1 }
829 @{$self->custom_icons};
830 $self->add_deleted_object($uuid) if @deleted;
834 ##############################################################################
838 \%all_data = $kdbx->custom_data;
839 $kdbx->custom_data(\%all_data);
841 \%data = $kdbx->custom_data($key);
842 $kdbx->custom_data($key => \%data);
843 $kdbx->custom_data(%data);
844 $kdbx->custom_data(key => $value, %data);
846 Get and set custom data. Custom data is metadata associated with a database.
848 Each data item can have a few attributes associated with it.
851 * C<key> - A unique text string identifier used to look up the data item (required)
852 * C<value> - A text string value (required)
853 * C<last_modification_time> (optional, KDBX4.1+)
859 $self->{meta}{custom_data} = shift if @_ == 1 && is_plain_hashref($_[0]);
860 return $self->{meta}{custom_data} //= {} if !@_;
862 my %args = @_ == 2 ? (key => shift, value => shift)
863 : @_ % 2 == 1 ? (key => shift, @_) : @_;
865 if (!$args{key} && !$args{value}) {
866 my %standard = (key => 1, value => 1, last_modification_time => 1);
867 my @other_keys = grep { !$standard{$_} } keys %args;
868 if (@other_keys == 1) {
869 my $key = $args{key} = $other_keys[0];
870 $args{value} = delete $args{$key};
874 my $key = $args{key} or throw 'Must provide a custom_data key to access
';
876 return $self->{meta}{custom_data}{$key} = $args{value} if is_plain_hashref($args{value});
878 while (my ($field, $value) = each %args) {
879 $self->{meta}{custom_data}{$key}{$field} = $value;
881 return $self->{meta}{custom_data}{$key};
884 =method custom_data_value
886 $value = $kdbx->custom_data_value($key);
888 Exactly the same as L</custom_data> except returns just the custom data's value rather than a structure of
889 attributes
. This
is a shortcut
for:
891 my $data = $kdbx->custom_data($key);
892 my $value = defined $data ? $data->{value
} : undef;
896 sub custom_data_value
{
898 my $data = $self->custom_data(@_) // return;
899 return $data->{value
};
902 =method public_custom_data
904 \
%all_data = $kdbx->public_custom_data;
905 $kdbx->public_custom_data(\
%all_data);
907 $value = $kdbx->public_custom_data($key);
908 $kdbx->public_custom_data($key => $value);
910 Get
and set public custom data
. Public custom data
is similar to custom data but different
in some important
911 ways
. Public custom data
:
914 * can store strings, booleans and up to 64-bit integer values (custom data can only store text values)
915 * is NOT encrypted within a KDBX file (hence the "public" part of the name)
916 * is a plain hash/dict of key-value pairs with no other associated fields (like modification times)
920 sub public_custom_data
{
922 $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
} = shift if @_ == 1 && is_plain_hashref
($_[0]);
923 return $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
} //= {} if !@_;
925 my $key = shift or throw
'Must provide a public_custom_data key to access';
926 $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
}{$key} = shift if @_;
927 return $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
}{$key};
930 ##############################################################################
937 # my %options = @_; # prefer_old / prefer_new
938 # $other->merge_from($self);
945 # die 'Not implemented';
948 =method add_deleted_object
950 $kdbx->add_deleted_object($uuid);
952 Add a UUID to the deleted objects list
. This list
is used to support automatic database merging
.
954 You typically
do not need to call this yourself because the list will be populated automatically as objects
959 sub add_deleted_object
{
963 # ignore null and meta stream UUIDs
964 return if $uuid eq UUID_NULL
|| $uuid eq '0' x
16;
966 $self->deleted_objects->{$uuid} = {
968 deletion_time
=> scalar gmtime,
972 =method remove_deleted_object
974 $kdbx->remove_deleted_object($uuid);
976 Remove a UUID from the deleted objects list
. This list
is used to support automatic database merging
.
978 You typically
do not need to call this yourself because the list will be maintained automatically as objects
983 sub remove_deleted_object
{
986 delete $self->deleted_objects->{$uuid};
989 =method clear_deleted_objects
991 Remove all UUIDs from the deleted objects list
. This list
is used to support automatic database merging
, but
992 if you don
't need merging then you can clear deleted objects to reduce the database file size.
996 sub clear_deleted_objects {
998 %{$self->deleted_objects} = ();
1001 ##############################################################################
1003 =method resolve_reference
1005 $string = $kdbx->resolve_reference($reference);
1006 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
1008 Resolve a L<field reference|https://keepass.info/help/base/fieldrefs.html>. A field reference is a kind of
1009 string placeholder. You can use a field reference to refer directly to a standard field within an entry. Field
1010 references are resolved automatically while expanding entry strings (i.e. replacing placeholders), but you can
1011 use this method to resolve on-the-fly references that aren't part of any actual string
in the database
.
1013 If the reference
does not resolve to any field
, C
<undef> is returned
. If the reference resolves to multiple
1014 fields
, only the first one
is returned
(in the same order as iterated by L
</entries
>). To avoid ambiguity
, you
1015 can refer to a specific entry by its UUID
.
1017 The syntax of a reference
is: C
<< {REF
:<WantedField
>@<SearchIn
>:<Text
>} >>. C
<Text
> is a
1018 L
</"Simple Expression">. C
<WantedField
> and C
<SearchIn
> are both single character codes representing a field
:
1027 * C<O> - Other custom strings
1029 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
1033 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
1035 my $username = $kdbx->resolve_reference('{REF:U@T:"My Bank"}');
1036 # OR the {REF:...} wrapper is optional
1037 my $username = $kdbx->resolve_reference('U@T:"My Bank"');
1038 # OR separate the arguments
1039 my $username = $kdbx->resolve_reference(U => T => '"My Bank"');
1041 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
1044 To get the I<Password> string of a specific entry (identified by its UUID):
1046 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
1050 sub resolve_reference
{
1052 my $wanted = shift // return;
1053 my $search_in = shift;
1056 if (!defined $text) {
1057 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
1058 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
1060 $wanted && $search_in && nonempty
($text) or return;
1063 T
=> 'expand_title',
1064 U
=> 'expand_username',
1065 P
=> 'expand_password',
1067 N
=> 'expand_notes',
1069 O
=> 'other_strings',
1071 $wanted = $fields{$wanted} or return;
1072 $search_in = $fields{$search_in} or return;
1074 my $query = $search_in eq 'uuid' ? query
($search_in => uuid
($text))
1075 : simple_expression_query
($text, '=~', $search_in);
1077 my $entry = $self->entries->grep($query)->next;
1080 return $entry->$wanted;
1083 our %PLACEHOLDERS = (
1084 # 'PLACEHOLDER' => sub { my ($entry, $arg) = @_; ... };
1085 'TITLE' => sub { $_[0]->expand_title },
1086 'USERNAME' => sub { $_[0]->expand_username },
1087 'PASSWORD' => sub { $_[0]->expand_password },
1088 'NOTES' => sub { $_[0]->expand_notes },
1089 'S:' => sub { $_[0]->string_value($_[1]) },
1090 'URL' => sub { $_[0]->expand_url },
1091 'URL:RMVSCM' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1092 'URL:WITHOUTSCHEME' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1093 'URL:SCM' => sub { (split_url
($_[0]->url))[0] },
1094 'URL:SCHEME' => sub { (split_url
($_[0]->url))[0] }, # non-standard
1095 'URL:HOST' => sub { (split_url
($_[0]->url))[2] },
1096 'URL:PORT' => sub { (split_url
($_[0]->url))[3] },
1097 'URL:PATH' => sub { (split_url
($_[0]->url))[4] },
1098 'URL:QUERY' => sub { (split_url
($_[0]->url))[5] },
1099 'URL:HASH' => sub { (split_url
($_[0]->url))[6] }, # non-standard
1100 'URL:FRAGMENT' => sub { (split_url
($_[0]->url))[6] }, # non-standard
1101 'URL:USERINFO' => sub { (split_url
($_[0]->url))[1] },
1102 'URL:USERNAME' => sub { (split_url
($_[0]->url))[7] },
1103 'URL:PASSWORD' => sub { (split_url
($_[0]->url))[8] },
1104 'UUID' => sub { local $_ = format_uuid
($_[0]->uuid); s/-//g; $_ },
1105 'REF:' => sub { $_[0]->kdbx->resolve_reference($_[1]) },
1106 'INTERNETEXPLORER' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('iexplore') },
1107 'FIREFOX' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('firefox') },
1108 'GOOGLECHROME' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('google-chrome') },
1109 'OPERA' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('opera') },
1110 'SAFARI' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('safari') },
1111 'APPDIR' => sub { load_optional
('FindBin'); $FindBin::Bin
},
1112 'GROUP' => sub { my $p = $_[0]->group; $p ? $p->name : undef },
1113 'GROUP_PATH' => sub { $_[0]->path },
1114 'GROUP_NOTES' => sub { my $p = $_[0]->group; $p ? $p->notes : undef },
1123 'ENV:' => sub { $ENV{$_[1]} },
1124 'ENV_DIRSEP' => sub { load_optional
('File::Spec')->catfile('', '') },
1125 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
1128 'DT_SIMPLE' => sub { localtime-
>strftime('%Y%m%d%H%M%S') },
1129 'DT_YEAR' => sub { localtime-
>strftime('%Y') },
1130 'DT_MONTH' => sub { localtime-
>strftime('%m') },
1131 'DT_DAY' => sub { localtime-
>strftime('%d') },
1132 'DT_HOUR' => sub { localtime-
>strftime('%H') },
1133 'DT_MINUTE' => sub { localtime-
>strftime('%M') },
1134 'DT_SECOND' => sub { localtime-
>strftime('%S') },
1135 'DT_UTC_SIMPLE' => sub { gmtime-
>strftime('%Y%m%d%H%M%S') },
1136 'DT_UTC_YEAR' => sub { gmtime-
>strftime('%Y') },
1137 'DT_UTC_MONTH' => sub { gmtime-
>strftime('%m') },
1138 'DT_UTC_DAY' => sub { gmtime-
>strftime('%d') },
1139 'DT_UTC_HOUR' => sub { gmtime-
>strftime('%H') },
1140 'DT_UTC_MINUTE' => sub { gmtime-
>strftime('%M') },
1141 'DT_UTC_SECOND' => sub { gmtime-
>strftime('%S') },
1148 'HMACOTP' => sub { $_[0]->hmac_otp },
1149 'TIMEOTP' => sub { $_[0]->time_otp },
1150 'C:' => sub { '' }, # comment
1158 ##############################################################################
1164 Encrypt all protected strings
and binaries
in a database
. The encrypted data
is stored
in
1165 a L
<File
::KDBX
::Safe
> associated with the database
and the actual
values will be replaced with C
<undef> to
1166 indicate their protected
state. Returns itself to allow
method chaining
.
1168 You can call C
<lock> on an already-locked database to memory-protect any unprotected strings
and binaries
1169 added after the
last time the database was locked
.
1175 $SAFE{$self} = shift if @_;
1179 sub _remove_safe
{ delete $SAFE{$_[0]} }
1184 # Find things to lock:
1186 $self->entries(history
=> 1)->each(sub {
1187 my $strings = $_->strings;
1188 for my $string_key (keys %$strings) {
1189 my $string = $strings->{$string_key};
1190 push @strings, $string if $string->{protect
} // $self->memory_protection($string_key);
1192 push @strings, grep { $_->{protect
} } values %{$_->binaries};
1194 return $self if !@strings; # nothing to do
1196 if (my $safe = $self->_safe) {
1197 $safe->add(\
@strings);
1200 $self->_safe(File
::KDBX
::Safe-
>new(\
@strings));
1209 Decrypt all protected strings
and binaries
in a database
, replacing C
<undef> value placeholders with their
1210 actual
, unprotected
values. Returns itself to allow
method chaining
.
1216 my $safe = $self->_safe or return $self;
1219 $self->_remove_safe;
1224 =method unlock_scoped
1226 $guard = $kdbx->unlock_scoped;
1228 Unlock a database temporarily
, relocking
when the guard
is released
(typically at the end of a scope
). Returns
1229 C
<undef> if the database
is already unlocked
.
1231 See L
</lock> and L</unlock
>.
1236 my $guard = $kdbx->unlock_scoped;
1239 # $kdbx is now memory-locked
1244 throw
'Programmer error: Cannot call unlock_scoped in void context' if !defined wantarray;
1246 return if !$self->is_locked;
1247 require Scope
::Guard
;
1248 my $guard = Scope
::Guard-
>new(sub { $self->lock });
1255 $string = $kdbx->peek(\
%string);
1256 $string = $kdbx->peek(\
%binary);
1258 Peek at the value of a protected string
or binary without unlocking the whole database
. The argument can be
1259 a string
or binary hashref as returned by L
<File
::KDBX
::Entry
/string> or L<File::KDBX::Entry/binary
>.
1266 my $safe = $self->_safe or return;
1267 return $safe->peek($string);
1272 $bool = $kdbx->is_locked;
1274 Get whether
or not a database
's contents are in a locked (i.e. memory-protected) state. If this is true, then
1275 some or all of the protected strings and binaries within the database will be unavailable (literally have
1276 C<undef> values) until L</unlock> is called.
1280 sub is_locked { !!$_[0]->_safe }
1282 ##############################################################################
1285 # - Fixer tool. Can repair inconsistencies, including:
1286 # - Orphaned binaries... not really a thing anymore since we now distribute binaries amongst entries
1287 # - Unused custom icons (OFF, data loss)
1289 # - All data types are valid
1290 # - date times are correct
1292 # - All UUIDs refer to things that exist
1293 # - previous parent group
1295 # - last selected group
1296 # - last visible group
1297 # - Enforce history size limits (ON)
1298 # - Check headers/meta (ON)
1299 # - Duplicate deleted objects (ON)
1300 # - Duplicate window associations (OFF)
1301 # - Header UUIDs match known ciphers/KDFs?
1304 =method remove_empty_groups
1306 $kdbx->remove_empty_groups;
1308 Remove groups with no subgroups and no entries.
1312 sub remove_empty_groups {
1315 $self->groups(algorithm => 'dfs
')
1316 ->where(-true => 'is_empty
')
1317 ->each(sub { push @removed, $_->remove });
1321 =method remove_unused_icons
1323 $kdbx->remove_unused_icons;
1325 Remove icons that are not associated with any entry or group in the database.
1329 sub remove_unused_icons {
1331 my %icons = map { $_->{uuid} => 0 } @{$self->custom_icons};
1333 $self->objects->each(sub { ++$icons{$_->custom_icon_uuid // ''} });
1336 push @removed, $self->remove_custom_icon($_) for grep { $icons{$_} == 0 } keys %icons;
1340 =method remove_duplicate_icons
1342 $kdbx->remove_duplicate_icons;
1344 Remove duplicate icons as determined by hashing the icon data.
1348 sub remove_duplicate_icons {
1353 for my $icon (@{$self->custom_icons}) {
1354 my $digest = digest_data('SHA256
', $icon->{data});
1355 if (my $other = $seen{$digest}) {
1356 $dup{$icon->{uuid}} = $other->{uuid};
1359 $seen{$digest} = $icon;
1364 while (my ($old_uuid, $new_uuid) = each %dup) {
1366 ->where(custom_icon_uuid => $old_uuid)
1367 ->each(sub { $_->custom_icon_uuid($new_uuid) });
1368 push @removed, $self->remove_custom_icon($old_uuid);
1373 =method prune_history
1375 $kdbx->prune_history(%options);
1377 Remove just as many older historical entries as necessary to get under certain limits.
1380 * C<max_items> - Maximum number of historical entries to keep (default: value of L</history_max_items>, no
1382 * C<max_size> - Maximum total size (in bytes) of historical entries to keep (default: value of
1383 L</history_max_size>, no limit: -1)
1384 * C<max_age> - Maximum age (in days) of historical entries to keep (default: value of
1385 L</maintenance_history_days>, no limit: -1)
1393 my $max_items = $args{max_items} // $self->history_max_items // HISTORY_DEFAULT_MAX_ITEMS;
1394 my $max_size = $args{max_size} // $self->history_max_size // HISTORY_DEFAULT_MAX_SIZE;
1395 my $max_age = $args{max_age} // $self->maintenance_history_days // HISTORY_DEFAULT_MAX_AGE;
1398 $self->entries->each(sub {
1399 push @removed, $_->prune_history(
1400 max_items => $max_items,
1401 max_size => $max_size,
1402 max_age => $max_age,
1408 =method randomize_seeds
1410 $kdbx->randomize_seeds;
1412 Set various keys, seeds and IVs to random values. These values are used by the cryptographic functions that
1413 secure the database when dumped. The attributes that will be randomized are:
1417 * L</inner_random_stream_key>
1419 * L</stream_start_bytes>
1420 * L</transform_seed>
1422 Randomizing these values has no effect on a loaded database. These are only used when a database is dumped.
1423 You normally do not need to call this method explicitly because the dumper does it for you by default.
1427 sub randomize_seeds {
1430 $iv_size = $self->cipher(key => "\0" x 32)->iv_size if KDBX_VERSION_4_0 <= $self->version;
1431 $self->encryption_iv(random_bytes($iv_size));
1432 $self->inner_random_stream_key(random_bytes(64));
1433 $self->master_seed(random_bytes(32));
1434 $self->stream_start_bytes(random_bytes(32));
1435 $self->transform_seed(random_bytes(32));
1438 ##############################################################################
1443 $key = $kdbx->key($key);
1444 $key = $kdbx->key($primitive);
1446 Get or set a L<File::KDBX::Key>. This is the master key (e.g. a password or a key file that can decrypt
1447 a database). You can also pass a primitive castable to a B<Key>. See L<File::KDBX::Key/new> for an explanation
1448 of what the primitive can be.
1450 You generally don't need to call this directly because you can provide the key directly to the loader
or
1451 dumper
when loading
or dumping a KDBX file
.
1457 $KEYS{$self} = File
::KDBX
::Key-
>new(@_) if @_;
1461 =method composite_key
1463 $key = $kdbx->composite_key($key);
1464 $key = $kdbx->composite_key($primitive);
1466 Construct a L
<File
::KDBX
::Key
::Composite
> from a B
<Key
> or primitive
. See L
<File
::KDBX
::Key
/new
> for an
1467 explanation of what the primitive can be
. If the primitive
does not represent a composite key
, it will be
1470 You generally don
't need to call this directly. The loader and dumper use it to transform a master key into
1471 a raw encryption key.
1477 require File::KDBX::Key::Composite;
1478 return File::KDBX::Key::Composite->new(@_);
1483 $kdf = $kdbx->kdf(%options);
1484 $kdf = $kdbx->kdf(\%parameters, %options);
1486 Get a L<File::KDBX::KDF> (key derivation function).
1491 * C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
1497 my %args = @_ % 2 == 1 ? (params => shift, @_) : @_;
1499 my $params = $args{params};
1501 $params //= $self->kdf_parameters;
1502 $params = {%{$params || {}}};
1504 if (empty $params || !defined $params->{+KDF_PARAM_UUID}) {
1505 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES;
1507 if ($params->{+KDF_PARAM_UUID} eq KDF_UUID_AES) {
1508 # AES_CHALLENGE_RESPONSE is equivalent to AES if there are no challenge-response keys, and since
1509 # non-KeePassXC implementations don't support challenge-response
keys anyway
, there
's no problem with
1510 # always using AES_CHALLENGE_RESPONSE for all KDBX4+ databases.
1511 # For compatibility, we should not *write* AES_CHALLENGE_RESPONSE, but the dumper handles that.
1512 if ($self->version >= KDBX_VERSION_4_0) {
1513 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES_CHALLENGE_RESPONSE;
1515 $params->{+KDF_PARAM_AES_SEED} //= $self->transform_seed;
1516 $params->{+KDF_PARAM_AES_ROUNDS} //= $self->transform_rounds;
1519 require File::KDBX::KDF;
1520 return File::KDBX::KDF->new(%$params);
1523 sub transform_seed {
1525 my $param = KDF_PARAM_AES_SEED; # Short cut: Argon2 uses the same parameter name ("S")
1526 $self->headers->{+HEADER_TRANSFORM_SEED} =
1527 $self->headers->{+HEADER_KDF_PARAMETERS}{$param} = shift if @_;
1528 $self->headers->{+HEADER_TRANSFORM_SEED} =
1529 $self->headers->{+HEADER_KDF_PARAMETERS}{$param} //= random_bytes(32);
1532 sub transform_rounds {
1534 require File::KDBX::KDF;
1535 my $info = $File::KDBX::KDF::ROUNDS_INFO{$self->kdf_parameters->{+KDF_PARAM_UUID} // ''} //
1536 $File::KDBX::KDF::DEFAULT_ROUNDS_INFO;
1537 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1538 $self->headers->{+HEADER_KDF_PARAMETERS}{$info->{p}} = shift if @_;
1539 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1540 $self->headers->{+HEADER_KDF_PARAMETERS}{$info->{p}} //= $info->{d};
1545 $cipher = $kdbx->cipher(key => $key);
1546 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
1548 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
1550 A key is required. This should be a raw encryption key made up of a fixed number of octets (depending on the
1551 cipher), not a L<File::KDBX::Key> or primitive.
1553 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
1554 C<< $kdbx->headers->{encryption_iv} >>.
1556 You generally don't need to call this directly
. The loader
and dumper
use it to decrypt
and encrypt KDBX
1565 $args{uuid
} //= $self->cipher_id;
1566 $args{iv
} //= $self->encryption_iv;
1568 require File
::KDBX
::Cipher
;
1569 return File
::KDBX
::Cipher-
>new(%args);
1572 =method random_stream
1574 $cipher = $kdbx->random_stream;
1575 $cipher = $kdbx->random_stream(id
=> $stream_id, key
=> $key);
1577 Get a L
<File
::KDBX
::Cipher
::Stream
> for decrypting
and encrypting protected
values.
1579 If
not passed
, the ID
and encryption key comes from C
<< $kdbx->headers->{inner_random_stream_id
} >> and
1580 C
<< $kdbx->headers->{inner_random_stream_key
} >> (respectively
) for KDBX3 files
and from
1581 C
<< $kdbx->inner_headers->{inner_random_stream_key
} >> and
1582 C
<< $kdbx->inner_headers->{inner_random_stream_id
} >> (respectively
) for KDBX4 files
.
1584 You generally don
't need to call this directly. The loader and dumper use it to scramble protected strings.
1592 $args{stream_id} //= delete $args{id} // $self->inner_random_stream_id;
1593 $args{key} //= $self->inner_random_stream_key;
1595 require File::KDBX::Cipher;
1596 File::KDBX::Cipher->new(%args);
1599 sub inner_random_stream_id {
1601 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1602 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} = shift if @_;
1603 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1604 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} //= do {
1605 my $version = $self->minimum_version;
1606 $version < KDBX_VERSION_4_0 ? STREAM_ID_SALSA20 : STREAM_ID_CHACHA20;
1610 sub inner_random_stream_key {
1613 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1615 erase \$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
1616 erase \$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
1617 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1618 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} = shift;
1620 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1621 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} //= random_bytes(64); # 32
1624 #########################################################################################
1626 sub _handle_signal {
1632 'entry
.added
' => \&_handle_object_added,
1633 'group
.added
' => \&_handle_object_added,
1634 'entry
.removed
' => \&_handle_object_removed,
1635 'group
.removed
' => \&_handle_object_removed,
1636 'entry
.uuid
.changed
' => \&_handle_entry_uuid_changed,
1637 'group
.uuid
.changed
' => \&_handle_group_uuid_changed,
1639 my $handler = $handlers{$type} or return;
1640 $self->$handler($object, @_);
1643 sub _handle_object_added {
1646 $self->remove_deleted_object($object->uuid);
1649 sub _handle_object_removed {
1652 my $old_uuid = $object->{uuid} // return;
1654 my $meta = $self->meta;
1655 $self->recycle_bin_uuid(UUID_NULL) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
1656 $self->entry_templates_group(UUID_NULL) if $old_uuid eq ($meta->{entry_templates_group} // '');
1657 $self->last_selected_group(UUID_NULL) if $old_uuid eq ($meta->{last_selected_group} // '');
1658 $self->last_top_visible_group(UUID_NULL) if $old_uuid eq ($meta->{last_top_visible_group} // '');
1660 $self->add_deleted_object($old_uuid);
1663 sub _handle_entry_uuid_changed {
1666 my $new_uuid = shift;
1667 my $old_uuid = shift // return;
1669 my $old_pretty = format_uuid($old_uuid);
1670 my $new_pretty = format_uuid($new_uuid);
1671 my $fieldref_match = qr/\{REF:([TUPANI])\@I:\Q$old_pretty\E\}/is;
1673 $self->entries->each(sub {
1674 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1676 for my $string (values %{$_->strings}) {
1677 next if !defined $string->{value} || $string->{value} !~ $fieldref_match;
1678 my $txn = $_->begin_work;
1679 $string->{value} =~ s/$fieldref_match/{REF:$1\@I:$new_pretty}/g;
1685 sub _handle_group_uuid_changed {
1688 my $new_uuid = shift;
1689 my $old_uuid = shift // return;
1691 my $meta = $self->meta;
1692 $self->recycle_bin_uuid($new_uuid) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
1693 $self->entry_templates_group($new_uuid) if $old_uuid eq ($meta->{entry_templates_group} // '');
1694 $self->last_selected_group($new_uuid) if $old_uuid eq ($meta->{last_selected_group} // '');
1695 $self->last_top_visible_group($new_uuid) if $old_uuid eq ($meta->{last_top_visible_group} // '');
1697 $self->groups->each(sub {
1698 $_->last_top_visible_entry($new_uuid) if $old_uuid eq ($_->{last_top_visible_entry} // '');
1699 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1701 $self->entries->each(sub {
1702 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1706 #########################################################################################
1722 =attr deleted_objects
1724 Hash of UUIDs for objects that have been deleted. This includes groups, entries and even custom icons.
1728 Bytes contained within the encrypted layer of a KDBX file. This is only set when using
1729 L<File::KDBX::Loader::Raw>.
1733 A text string associated with the database stored unencrypted in the file header. Often unset.
1737 The UUID of a cipher used to encrypt the database when stored as a file.
1739 See L<File::KDBX::Cipher>.
1741 =attr compression_flags
1743 Configuration for whether or not and how the database gets compressed. See
1744 L<File::KDBX::Constants/":compression">.
1748 The master seed is a string of 32 random bytes that is used as salt in hashing the master key when loading
1749 and saving the database. If a challenge-response key is used in the master key, the master seed is also the
1752 The master seed I<should> be changed each time the database is saved to file.
1754 =attr transform_seed
1756 The transform seed is a string of 32 random bytes that is used in the key derivation function, either as the
1757 salt or the key (depending on the algorithm).
1759 The transform seed I<should> be changed each time the database is saved to file.
1761 =attr transform_rounds
1763 The number of rounds or iterations used in the key derivation function. Increasing this number makes loading
1764 and saving the database slower in order to make dictionary and brute force attacks more costly.
1768 The initialization vector used by the cipher.
1770 The encryption IV I<should> be changed each time the database is saved to file.
1772 =attr inner_random_stream_key
1774 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1775 within the database.
1777 =attr stream_start_bytes
1779 A string of 32 random bytes written in the header and encrypted in the body. If the bytes do not match when
1780 loading a file then the wrong master key was used or the file is corrupt. Only KDBX 2 and KDBX 3 files use
1781 this. KDBX 4 files use an improved HMAC method to verify the master key and data integrity of the header and
1784 =attr inner_random_stream_id
1786 A number indicating the cipher algorithm used to encrypt the protected strings within the database, usually
1787 Salsa20 or ChaCha20. See L<File::KDBX::Constants/":random_stream">.
1789 =attr kdf_parameters
1791 A hash/dict of key-value pairs used to configure the key derivation function. This is the KDBX4+ way to
1792 configure the KDF, superceding L</transform_seed> and L</transform_rounds>.
1796 The name of the software used to generate the KDBX file.
1800 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1804 Name of the database.
1806 =attr database_name_changed
1808 Timestamp indicating when the database name was last changed.
1810 =attr database_description
1812 Description of the database
1814 =attr database_description_changed
1816 Timestamp indicating when the database description was last changed.
1818 =attr default_username
1820 When a new entry is created, the I<UserName> string will be populated with this value.
1822 =attr default_username_changed
1824 Timestamp indicating when the default username was last changed.
1828 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
1829 use this to help users visually distinguish between different databases.
1831 =attr master_key_changed
1833 Timestamp indicating when the master key was last changed.
1835 =attr master_key_change_rec
1837 Number of days until the agent should prompt to recommend changing the master key.
1839 =attr master_key_change_force
1841 Number of days until the agent should prompt to force changing the master key.
1843 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
1844 B<File::KDBX> does NOT enforce it.
1848 Array of custom icons that can be associated with groups and entries.
1850 This list can be managed with the methods L</add_custom_icon> and L</remove_custom_icon>.
1852 =attr recycle_bin_enabled
1854 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1856 =attr recycle_bin_uuid
1858 The UUID of a group used to store thrown-away groups and entries.
1860 =attr recycle_bin_changed
1862 Timestamp indicating when the recycle bin group was last changed.
1864 =attr entry_templates_group
1866 The UUID of a group containing template entries used when creating new entries.
1868 =attr entry_templates_group_changed
1870 Timestamp indicating when the entry templates group was last changed.
1872 =attr last_selected_group
1874 The UUID of the previously-selected group.
1876 =attr last_top_visible_group
1878 The UUID of the group visible at the top of the list.
1880 =attr history_max_items
1882 The maximum number of historical entries that should be kept for each entry. Default is 10.
1884 =attr history_max_size
1886 The maximum total size (in bytes) that each individual entry's history
is allowed to grow
. Default
is 6 MiB
.
1888 =attr maintenance_history_days
1890 The maximum age
(in days
) historical entries should be kept
. Default it
365.
1892 =attr settings_changed
1894 Timestamp indicating
when the database settings were
last updated
.
1898 Alias of the L
</memory_protection
> setting
for the I
<Title
> string
.
1900 =attr protect_username
1902 Alias of the L
</memory_protection
> setting
for the I
<UserName
> string
.
1904 =attr protect_password
1906 Alias of the L
</memory_protection
> setting
for the I
<Password
> string
.
1910 Alias of the L
</memory_protection
> setting
for the I
<URL
> string
.
1914 Alias of the L
</memory_protection
> setting
for the I
<Notes
> string
.
1918 #########################################################################################
1920 sub TO_JSON
{ +{%{$_[0]}} }
1925 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
1931 # Create a new database from scratch
1932 my $kdbx = File::KDBX->new;
1934 # Add some objects to the database
1935 my $group = $kdbx->add_group(
1936 name => 'Passwords',
1938 my $entry = $group->add_entry(
1940 username => 'mreynolds',
1941 password => 's3cr3t',
1944 # Save the database to the filesystem
1945 $kdbx->dump_file('passwords.kdbx', 'masterpw changeme');
1947 # Load the database from the filesystem into a new database instance
1948 my $kdbx2 = File::KDBX->load_file('passwords.kdbx', 'masterpw changeme');
1950 # Iterate over database entries, print entry titles
1951 $kdbx2->entries->each(sub($entry, @) {
1952 say 'Entry: ', $entry->title;
1955 See L</RECIPES> for more examples.
1959 B<File::KDBX> provides everything you need to work with KDBX databases. A KDBX database is a hierarchical
1960 object database which is commonly used to store secret information securely. It was developed for the KeePass
1961 password safe. See L</"Introduction to KDBX"> for more information about KDBX.
1963 This module lets you query entries, create new entries, delete entries, modify entries and more. The
1964 distribution also includes various parsers and generators for serializing and persisting databases.
1966 The design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
1967 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
1968 that works well in most cases but has a small backlog of bugs and security issues and also does not work with
1969 newer KDBX version 4 files. If you're coming here from the B<File::KeePass> world, you might be interested in
1970 L<File::KeePass::KDBX> that is a drop-in replacement for B<File::KeePass> that uses B<File::KDBX> for storage.
1972 This software is a B<pre-1.0 release>. The interface should be considered pretty stable, but there might be
1973 minor changes up until a 1.0 release. Breaking changes will be noted in the F<Changes> file.
1978 * ☑ Read and write KDBX version 3 - version 4.1
1979 * ☑ Read and write KDB files (requires L<File::KeePass>)
1980 * ☑ Unicode character strings
1981 * ☑ L</"Simple Expression"> Searching
1982 * ☑ L<Placeholders|File::KDBX::Entry/Placeholders> and L<field references|/resolve_reference>
1983 * ☑ L<One-time passwords|File::KDBX::Entry/"One-time Passwords">
1984 * ☑ L<Very secure|/SECURITY>
1985 * ☑ L</"Memory Protection">
1986 * ☑ Challenge-response key components, like L<YubiKey|File::KDBX::Key::YubiKey>
1987 * ☑ Variety of L<key file|File::KDBX::Key::File> types: binary, hexed, hashed, XML v1 and v2
1988 * ☑ Pluggable registration of different kinds of ciphers and key derivation functions
1989 * ☑ Built-in database maintenance functions
1990 * ☑ Pretty fast, with L<XS optimizations|File::KDBX::XS> available
1991 * ☒ Database synchronization / merging (not yet)
1993 =head2 Introduction to KDBX
1995 A KDBX database consists of a tree of I<groups> and I<entries>, with a single I<root> group. Entries can
1996 contain zero or more key-value pairs of I<strings> and zero or more I<binaries> (i.e. octet strings). Groups,
1997 entries, strings and binaries: that's the KDBX vernacular. A small amount of metadata (timestamps, etc.) is
1998 associated with each entry, group and the database as a whole.
2000 You can think of a KDBX database kind of like a file system, where groups are directories, entries are files,
2001 and strings and binaries make up a file's contents.
2003 Databases are typically persisted as encrypted, compressed files. They are usually accessed directly (i.e.
2004 not over a network). The primary focus of this type of database is data security. It is ideal for storing
2005 relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as
2006 have the correct I<master key>. Even if the database file were to be "leaked" to the public Internet, it
2007 should be virtually impossible to crack with a strong key. The KDBX format is most often used by password
2008 managers to store passwords so that users can know a single strong password and not have to reuse passwords
2009 across different websites. See L</SECURITY> for an overview of security considerations.
2013 =head2 Create a new database
2015 my $kdbx = File::KDBX->new;
2017 my $group = $kdbx->add_group(name => 'Passwords);
2018 my $entry = $group->add_entry(
2019 title => 'WayneCorp',
2020 username => 'bwayne',
2021 password => 'iambatman',
2022 url => 'https://example.com/login'
2024 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
2026 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
2028 =head2 Read an existing database
2030 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
2031 $kdbx->unlock; # cause $entry->password below to be defined
2033 $kdbx->entries->each(sub($entry, @) {
2034 say 'Found password for: ', $entry->title;
2035 say ' Username: ', $entry->username;
2036 say ' Password: ', $entry->password;
2039 =head2 Search for entries
2041 my @entries = $kdbx->entries(searching => 1)
2042 ->grep(title => 'WayneCorp')
2043 ->each; # return all matches
2045 The C<searching> option limits results to only entries within groups with searching enabled. Other options are
2046 also available. See L</entries>.
2048 See L</QUERY> for many more query examples.
2050 =head2 Search for entries by auto-type window association
2052 my $window_title = 'WayneCorp - Mozilla Firefox';
2054 my $entries = $kdbx->entries(auto_type => 1)
2056 my ($ata) = grep { $_->{window} =~ /\Q$window_title\E/i } @{$_->auto_type_associations};
2057 return [$_, $ata->{keystroke_sequence}] if $ata;
2060 my ($entry, $keys) = @$_;
2061 say 'Entry title: ', $entry->title, ', key sequence: ', $keys;
2066 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
2068 =head2 Remove entries from a database
2071 ->grep(notes => {'=~' => qr/too old/i})
2072 ->each(sub { $_->recycle });
2074 Recycle all entries with the string "too old" appearing in the B<Notes> string.
2076 =head2 Remove empty groups
2078 $kdbx->groups(algorithm => 'dfs')
2079 ->where(-true => 'is_empty')
2082 With the search/iteration C<algorithm> set to "dfs", groups will be ordered deepest first and the root group
2083 will be last. This allows removing groups that only contain empty groups.
2085 This can also be done with one call to L</remove_empty_groups>.
2089 One of the biggest threats to your database security is how easily the encryption key can be brute-forced.
2090 Strong brute-force protection depends on:
2093 * Using unguessable passwords, passphrases and key files.
2094 * Using a brute-force resistent key derivation function.
2096 The first factor is up to you. This module does not enforce strong master keys. It is up to you to pick or
2097 generate strong keys.
2099 The KDBX format allows for the key derivation function to be tuned. The idea is that you want each single
2100 brute-force attempt to be expensive (in terms of time, CPU usage or memory usage), so that making a lot of
2101 attempts (which would be required if you have a strong master key) gets I<really> expensive.
2103 How expensive you want to make each attempt is up to you and can depend on the application.
2105 This and other KDBX-related security issues are covered here more in depth:
2106 L<https://keepass.info/help/base/security.html>
2108 Here are other security risks you should be thinking about:
2112 This distribution uses the excellent L<CryptX> and L<Crypt::Argon2> packages to handle all crypto-related
2113 functions. As such, a lot of the security depends on the quality of these dependencies. Fortunately these
2114 modules are maintained and appear to have good track records.
2116 The KDBX format has evolved over time to incorporate improved security practices and cryptographic functions.
2117 This package uses the following functions for authentication, hashing, encryption and random number
2123 * Argon2d & Argon2id
2128 * Salsa20 & ChaCha20
2131 At the time of this writing, I am not aware of any successful attacks against any of these functions. These
2132 are among the most-analyzed and widely-adopted crypto functions available.
2134 The KDBX format allows the body cipher and key derivation function to be configured. If a flaw is discovered
2135 in one of these functions, you can hopefully just switch to a better function without needing to update this
2136 software. A later software release may phase out the use of any functions which are no longer secure.
2138 =head2 Memory Protection
2140 It is not a good idea to keep secret information unencrypted in system memory for longer than is needed. The
2141 address space of your program can generally be read by a user with elevated privileges on the system. If your
2142 system is memory-constrained or goes into a hibernation mode, the contents of your address space could be
2143 written to a disk where it might be persisted for long time.
2145 There might be system-level things you can do to reduce your risk, like using swap encryption and limiting
2146 system access to your program's address space while your program is running.
2148 B<File::KDBX> helps minimize (but not eliminate) risk by keeping secrets encrypted in memory until accessed
2149 and zeroing out memory that holds secrets after they're no longer needed, but it's not a silver bullet.
2151 For one thing, the encryption key is stored in the same address space. If core is dumped, the encryption key
2152 is available to be found out. But at least there is the chance that the encryption key and the encrypted
2153 secrets won't both be paged out together while memory-constrained.
2155 Another problem is that some perls (somewhat notoriously) copy around memory behind the scenes willy nilly,
2156 and it's difficult know when perl makes a copy of a secret in order to be able to zero it out later. It might
2157 be impossible. The good news is that perls with SvPV copy-on-write (enabled by default beginning with perl
2158 5.20) are much better in this regard. With COW, it's mostly possible to know what operations will cause perl
2159 to copy the memory of a scalar string, and the number of copies will be significantly reduced. There is a unit
2160 test named F<t/memory-protection.t> in this distribution that can be run on POSIX systems to determine how
2161 well B<File::KDBX> memory protection is working.
2163 Memory protection also depends on how your application handles secrets. If your app code is handling scalar
2164 strings with secret information, it's up to you to make sure its memory is zeroed out when no longer needed.
2165 L<File::KDBX::Util/erase> et al. provide some tools to help accomplish this. Or if you're not too concerned
2166 about the risks memory protection is meant to mitigate, then maybe don't worry about it. The security policy
2167 of B<File::KDBX> is to try hard to keep secrets protected while in memory so that your app might claim a high
2168 level of security, in case you care about that.
2170 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
2172 Many systems allow programs to mark unswappable pages. Secret information should ideally be stored in such
2173 pages. You could potentially use L<mlockall(2)> (or equivalent for your system) in your own application to
2174 prevent the entire address space from being swapped.
2176 Some systems provide special syscalls for storing secrets in memory while keeping the encryption key outside
2177 of the program's address space, like C<CryptProtectMemory> for Windows. This could be a good option, though
2178 unfortunately not portable.
2182 To find things in a KDBX database, you should use a filtered iterator. If you have an iterator, such as
2183 returned by L</entries>, L</groups> or even L</objects> you can filter it using L<File::KDBX::Iterator/where>.
2185 my $filtered_entries = $kdbx->entries->where(\&query);
2187 A C<\&query> is just a subroutine that you can either write yourself or have generated for you from either
2188 a L</"Simple Expression"> or L</"Declarative Syntax">. It's easier to have your query generated, so I'll cover
2191 =head2 Simple Expression
2193 A simple expression is mostly compatible with the KeePass 2 implementation
2194 L<described here|https://keepass.info/help/base/search.html#mode_se>.
2196 An expression is a string with one or more space-separated terms. Terms with spaces can be enclosed in double
2197 quotes. Terms are negated if they are prefixed with a minus sign. A record must match every term on at least
2198 one of the given fields.
2200 So a simple expression is something like what you might type into a search engine. You can generate a simple
2201 expression query using L<File::KDBX::Util/simple_expression_query> or by passing the simple expression as
2202 a B<scalar reference> to C<where>.
2204 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
2206 my $entries = $kdbx->entries->where(\'canyon', qw[title]);
2208 Notice the first argument is a B<scalarref>. This disambiguates a simple expression from other types of
2209 queries covered below.
2211 As mentioned, a simple expression can have multiple terms. This simple expression query matches any entry that
2212 has the words "red" B<and> "canyon" anywhere in the title:
2214 my $entries = $kdbx->entries->where(\'red canyon', qw[title]);
2216 Each term in the simple expression must be found for an entry to match.
2218 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
2220 my $entries = $kdbx->entries->where(\'red -canyon', qw[title]);
2222 To search over multiple fields simultaneously, just list them all. To search for entries with "grocery" (but
2223 not "Foodland") in the title or notes:
2225 my $entries = $kdbx->entries->where(\'grocery -Foodland', qw[title notes]);
2227 The default operator is a case-insensitive regexp match, which is fine for searching text loosely. You can use
2228 just about any binary comparison operator that perl supports. To specify an operator, list it after the simple
2229 expression. For example, to search for any entry that has been used at least five times:
2231 my $entries = $kdbx->entries->where(\5, '>=', qw[usage_count]);
2233 It helps to read it right-to-left, like "usage_count is greater than or equal to 5".
2235 If you find the disambiguating structures to be distracting or confusing, you can also use the
2236 L<File::KDBX::Util/simple_expression_query> function as a more intuitive alternative. The following example is
2237 equivalent to the previous:
2239 my $entries = $kdbx->entries->where(simple_expression_query(5, '>=', qw[usage_count]));
2241 =head2 Declarative Syntax
2243 Structuring a declarative query is similar to L<SQL::Abstract/"WHERE CLAUSES">, but you don't have to be
2244 familiar with that module. Just learn by examples here.
2246 To search for all entries in a database titled "My Bank":
2248 my $entries = $kdbx->entries->where({ title => 'My Bank' });
2250 The query here is C<< { title => 'My Bank' } >>. A hashref can contain key-value pairs where the key is an
2251 attribute of the thing being searched for (in this case an entry) and the value is what you want the thing's
2252 attribute to be to consider it a match. In this case, the attribute we're using as our match criteria is
2253 L<File::KDBX::Entry/title>, a text field. If an entry has its title attribute equal to "My Bank", it's
2256 A hashref can contain multiple attributes. The search candidate will be a match if I<all> of the specified
2257 attributes are equal to their respective values. For example, to search for all entries with a particular URL
2260 my $entries = $kdbx->entries->where({
2261 url => 'https://example.com',
2265 To search for entries matching I<any> criteria, just change the hashref to an arrayref. To search for entries
2266 with a particular URL B<OR> username:
2268 my $entries = $kdbx->entries->where([ # <-- Notice the square bracket
2269 url => 'https://example.com',
2273 You can use different operators to test different types of attributes. The L<File::KDBX::Entry/icon_id>
2274 attribute is a number, so we should use a number comparison operator. To find entries using the smartphone
2277 my $entries = $kdbx->entries->where({
2278 icon_id => { '==', ICON_SMARTPHONE },
2281 Note: L<File::KDBX::Constants/ICON_SMARTPHONE> is just a constant from L<File::KDBX::Constants>. It isn't
2282 special to this example or to queries generally. We could have just used a literal number.
2284 The important thing to notice here is how we wrapped the condition in another hashref with a single key-value
2285 pair where the key is the name of an operator and the value is the thing to match against. The supported
2289 * C<eq> - String equal
2290 * C<ne> - String not equal
2291 * C<lt> - String less than
2292 * C<gt> - String greater than
2293 * C<le> - String less than or equal
2294 * C<ge> - String greater than or equal
2295 * C<==> - Number equal
2296 * C<!=> - Number not equal
2297 * C<< < >> - Number less than
2298 * C<< > >> - Number greater than
2299 * C<< <= >> - Number less than or equal
2300 * C<< >= >> - Number less than or equal
2301 * C<=~> - String match regular expression
2302 * C<!~> - String does not match regular expression
2303 * C<!> - Boolean false
2304 * C<!!> - Boolean true
2306 Other special operators:
2309 * C<-true> - Boolean true
2310 * C<-false> - Boolean false
2311 * C<-not> - Boolean false (alias for C<-false>)
2312 * C<-defined> - Is defined
2313 * C<-undef> - Is not defined
2314 * C<-empty> - Is empty
2315 * C<-nonempty> - Is not empty
2316 * C<-or> - Logical or
2317 * C<-and> - Logical and
2319 Let's see another example using an explicit operator. To find all groups except one in particular (identified
2320 by its L<File::KDBX::Group/uuid>), we can use the C<ne> (string not equal) operator:
2322 my $groups = $kdbx->groups->where(
2324 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
2328 Note: L<File::KDBX::Util/uuid> is a little utility function to convert a UUID in its pretty form into bytes.
2329 This utility function isn't special to this example or to queries generally. It could have been written with
2330 a literal such as C<"\x59\x6f\x75\x20\x61...">, but that's harder to read.
2332 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2334 Notice also that we didn't wrap the query in hashref curly-braces or arrayref square-braces. Those are
2335 optional. By default it will only match ALL attributes (as if there were curly-braces).
2337 Testing the truthiness of an attribute is a little bit different because it isn't a binary operation. To find
2338 all entries with the password quality check disabled:
2340 my $entries = $kdbx->entries->where('!' => 'quality_check');
2342 This time the string after the operator is the attribute name rather than a value to compare the attribute
2343 against. To test that a boolean value is true, use the C<!!> operator (or C<-true> if C<!!> seems a little too
2344 weird for your taste):
2346 my $entries = $kdbx->entries->where('!!' => 'quality_check');
2347 my $entries = $kdbx->entries->where(-true => 'quality_check'); # same thing
2349 Yes, there is also a C<-false> and a C<-not> if you prefer one of those over C<!>. C<-false> and C<-not>
2350 (along with C<-true>) are also special in that you can use them to invert the logic of a subquery. These are
2351 logically equivalent:
2353 my $entries = $kdbx->entries->where(-not => { title => 'My Bank' });
2354 my $entries = $kdbx->entries->where(title => { 'ne' => 'My Bank' });
2356 These special operators become more useful when combined with two more special operators: C<-and> and C<-or>.
2357 With these, it is possible to construct more interesting queries with groups of logic. For example:
2359 my $entries = $kdbx->entries->where({
2360 title => { '=~', qr/bank/ },
2363 notes => { '=~', qr/business/ },
2364 icon_id => { '==', ICON_TRASHCAN_FULL },
2369 In English, find entries where the word "bank" appears anywhere in the title but also do not have either the
2370 word "business" in the notes or are using the full trashcan icon.
2372 =head2 Subroutine Query
2374 Lastly, as mentioned at the top, you can ignore all this and write your own subroutine. Your subroutine will
2375 be called once for each object being searched over. The subroutine should match the candidate against whatever
2376 criteria you want and return true if it matches or false to skip. To do this, just pass your subroutine
2377 coderef to C<where>.
2379 To review the different types of queries, these are all equivalent to find all entries in the database titled
2382 my $entries = $kdbx->entries->where(\'"My Bank"', 'eq', qw[title]); # simple expression
2383 my $entries = $kdbx->entries->where(title => 'My Bank'); # declarative syntax
2384 my $entries = $kdbx->entries->where(sub { $_->title eq 'My Bank' }); # subroutine query
2386 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2388 All of these query mechanisms described in this section are just tools, each with its own set of limitations.
2389 If the tools are getting in your way, you can of course iterate over the contents of a database and implement
2390 your own query logic, like this:
2392 my $entries = $kdbx->entries;
2393 while (my $entry = $entries->next) {
2394 if (wanted($entry)) {
2395 do_something($entry);
2404 Iterators are the built-in way to navigate or walk the database tree. You get an iterator from L</entries>,
2405 L</groups> and L</objects>. You can specify the search algorithm to iterate over objects in different orders
2406 using the C<algorithm> option, which can be one of these L<constants|File::KDBX::Constants/":iteration">:
2409 * C<ITERATION_IDS> - Iterative deepening search (default)
2410 * C<ITERATION_DFS> - Depth-first search
2411 * C<ITERATION_BFS> - Breadth-first search
2413 When iterating over objects generically, groups always precede their direct entries (if any). When the
2414 C<history> option is used, current entries always precede historical entries.
2416 If you have a database tree like this:
2428 * IDS order of groups is: Root, Group1, Group2, Group3
2429 * IDS order of entries is: EntryA, EntryB, EntryC
2430 * IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC
2431 * DFS order of groups is: Group2, Group1, Group3, Root
2432 * DFS order of entries is: EntryB, EntryA, EntryC
2433 * DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root
2434 * BFS order of groups is: Root, Group1, Group3, Group2
2435 * BFS order of entries is: EntryA, EntryC, EntryB
2436 * BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB
2438 =head1 SYNCHRONIZING
2440 B<TODO> - This is a planned feature, not yet implemented.
2444 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
2445 mechanisms. Fatal errors are propagated using L<perlfunc/"die LIST"> and non-fatal errors (a.k.a. warnings)
2446 are propagated using L<perlfunc/"warn LIST"> while adhering to perl's L<warnings> system. If you're already
2447 familiar with these mechanisms, you can skip this section.
2449 You can catch fatal errors using L<perlfunc/"eval BLOCK"> (or something like L<Try::Tiny>) and non-fatal
2450 errors using C<$SIG{__WARN__}> (see L<perlvar/%SIG>). Examples:
2452 use File::KDBX::Error qw(error);
2454 my $key = ''; # uh oh
2456 $kdbx->load_file('whatever.kdbx', $key);
2458 if (my $error = error($@)) {
2459 handle_missing_key($error) if $error->type eq 'key.missing';
2463 or using C<Try::Tiny>:
2466 $kdbx->load_file('whatever.kdbx', $key);
2472 Catching non-fatal errors:
2475 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2477 $kdbx->load_file('whatever.kdbx', $key);
2479 handle_warnings(@warnings) if @warnings;
2481 By default perl prints warnings to C<STDERR> if you don't catch them. If you don't want to catch them and also
2482 don't want them printed to C<STDERR>, you can suppress them lexically (perl v5.28 or higher required):
2485 no warnings 'File::KDBX';
2492 local $File::KDBX::WARNINGS = 0;
2496 or globally in your program:
2498 $File::KDBX::WARNINGS = 0;
2500 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2504 This software will alter its behavior depending on the value of certain environment variables:
2507 * C<PERL_FILE_KDBX_XS> - Do not use L<File::KDBX::XS> if false (default: true)
2508 * C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
2509 * C<NO_FORK> - Do not fork if true (default: false)
2514 * L<KeePass Password Safe|https://keepass.info/> - The original KeePass
2515 * L<KeePassXC|https://keepassxc.org/> - Cross-Platform Password Manager written in C++
2516 * L<File::KeePass> has overlapping functionality. It's good but has a backlog of some pretty critical bugs and
2517 lacks support for newer KDBX features.
2523 [![Linux](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml)
2524 [![macOS](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml)
2525 [![Windows](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml)
2531 <a title="Linux" href="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml"><img src="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml/badge.svg"></a>
2532 <a title="macOS" href="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml"><img src="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml/badge.svg"></a>
2533 <a title="Windows" href="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml"><img src="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml/badge.svg"></a>