2 # ABSTRACT: Encrypted database to store secret text and files
7 use Crypt
::Digest
qw(digest_data);
8 use Crypt
::PRNG
qw(random_bytes);
9 use Devel
::GlobalDestruction
;
10 use File
::KDBX
::Constants
qw(:all :icon);
11 use File
::KDBX
::Error
;
13 use File
::KDBX
::Util
qw(:class :coercion :empty :search :uuid erase simple_expression_query snakify);
14 use Hash
::Util
::FieldHash
qw(fieldhashes);
15 use List
::Util
qw(any first);
16 use Ref
::Util
qw(is_ref is_arrayref is_plain_hashref);
17 use Scalar
::Util
qw(blessed);
22 our $VERSION = '0.800'; # VERSION
25 fieldhashes \
my (%SAFE, %KEYS);
32 return $_[0]->clone if @_ == 1 && blessed
$_[0] && $_[0]->isa($class);
34 my $self = bless {}, $class;
36 $self->_set_nonlazy_attributes if empty
$self;
40 sub DESTROY
{ local ($., $@, $!, $^E, $?); !in_global_destruction
and $_[0]->reset }
47 @$self{keys %args} = values %args;
55 erase
$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY
};
56 erase
$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY
};
67 return Storable
::dclone
($self);
76 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
87 @$self{keys %$clone} = values %$clone;
91 # Dualvars aren't cloned as dualvars, so coerce the compression flags.
92 $self->compression_flags($self->compression_flags);
94 $self->objects(history
=> 1)->each(sub { $_->kdbx($self) });
97 ##############################################################################
100 sub load
{ shift-
>_loader->load(@_) }
101 sub load_string
{ shift-
>_loader->load_string(@_) }
102 sub load_file
{ shift-
>_loader->load_file(@_) }
103 sub load_handle
{ shift-
>_loader->load_handle(@_) }
107 $self = $self->new if !ref $self;
108 require File
::KDBX
::Loader
;
109 File
::KDBX
::Loader-
>new(kdbx
=> $self);
113 sub dump { shift-
>_dumper->dump(@_) }
114 sub dump_string
{ shift-
>_dumper->dump_string(@_) }
115 sub dump_file
{ shift-
>_dumper->dump_file(@_) }
116 sub dump_handle
{ shift-
>_dumper->dump_handle(@_) }
120 $self = $self->new if !ref $self;
121 require File
::KDBX
::Dumper
;
122 File
::KDBX
::Dumper-
>new(kdbx
=> $self);
125 ##############################################################################
128 sub user_agent_string
{
130 sprintf('%s/%s (%s/%s; %s/%s; %s)',
131 __PACKAGE__
, $VERSION, @Config::Config
{qw(package version osname osvers archname)});
134 has sig1
=> KDBX_SIG1
, coerce
=> \
&to_number
;
135 has sig2
=> KDBX_SIG2_2
, coerce
=> \
&to_number
;
136 has version
=> KDBX_VERSION_3_1
, coerce
=> \
&to_number
;
138 has inner_headers
=> {};
141 has deleted_objects
=> {};
142 has raw
=> coerce
=> \
&to_string
;
145 has 'headers.comment' => '', coerce
=> \
&to_string
;
146 has 'headers.cipher_id' => CIPHER_UUID_CHACHA20
, coerce
=> \
&to_uuid
;
147 has 'headers.compression_flags' => COMPRESSION_GZIP
, coerce
=> \
&to_compression_constant
;
148 has 'headers.master_seed' => sub { random_bytes
(32) }, coerce
=> \
&to_string
;
149 has 'headers.encryption_iv' => sub { random_bytes
(16) }, coerce
=> \
&to_string
;
150 has 'headers.stream_start_bytes' => sub { random_bytes
(32) }, coerce
=> \
&to_string
;
151 has 'headers.kdf_parameters' => sub {
153 KDF_PARAM_UUID
() => KDF_UUID_AES
,
154 KDF_PARAM_AES_ROUNDS
() => $_[0]->headers->{+HEADER_TRANSFORM_ROUNDS
} // KDF_DEFAULT_AES_ROUNDS
,
155 KDF_PARAM_AES_SEED
() => $_[0]->headers->{+HEADER_TRANSFORM_SEED
} // random_bytes
(32),
158 # has 'headers.transform_seed' => sub { random_bytes(32) };
159 # has 'headers.transform_rounds' => 100_000;
160 # has 'headers.inner_random_stream_key' => sub { random_bytes(32) }; # 64 ?
161 # has 'headers.inner_random_stream_id' => STREAM_ID_CHACHA20;
162 # has 'headers.public_custom_data' => {};
165 has 'meta.generator' => '', coerce
=> \
&to_string
;
166 has 'meta.header_hash' => '', coerce
=> \
&to_string
;
167 has 'meta.database_name' => '', coerce
=> \
&to_string
;
168 has 'meta.database_name_changed' => sub { gmtime }, coerce
=> \
&to_time
;
169 has 'meta.database_description' => '', coerce
=> \
&to_string
;
170 has 'meta.database_description_changed' => sub { gmtime }, coerce
=> \
&to_time
;
171 has 'meta.default_username' => '', coerce
=> \
&to_string
;
172 has 'meta.default_username_changed' => sub { gmtime }, coerce
=> \
&to_time
;
173 has 'meta.maintenance_history_days' => 0, coerce
=> \
&to_number
;
174 has 'meta.color' => '', coerce
=> \
&to_string
;
175 has 'meta.master_key_changed' => sub { gmtime }, coerce
=> \
&to_time
;
176 has 'meta.master_key_change_rec' => -1, coerce
=> \
&to_number
;
177 has 'meta.master_key_change_force' => -1, coerce
=> \
&to_number
;
178 # has 'meta.memory_protection' => {};
179 has 'meta.custom_icons' => [];
180 has 'meta.recycle_bin_enabled' => true
, coerce
=> \
&to_bool
;
181 has 'meta.recycle_bin_uuid' => UUID_NULL
, coerce
=> \
&to_uuid
;
182 has 'meta.recycle_bin_changed' => sub { gmtime }, coerce
=> \
&to_time
;
183 has 'meta.entry_templates_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
184 has 'meta.entry_templates_group_changed' => sub { gmtime }, coerce
=> \
&to_time
;
185 has 'meta.last_selected_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
186 has 'meta.last_top_visible_group' => UUID_NULL
, coerce
=> \
&to_uuid
;
187 has 'meta.history_max_items' => HISTORY_DEFAULT_MAX_ITEMS
, coerce
=> \
&to_number
;
188 has 'meta.history_max_size' => HISTORY_DEFAULT_MAX_SIZE
, coerce
=> \
&to_number
;
189 has 'meta.settings_changed' => sub { gmtime }, coerce
=> \
&to_time
;
190 # has 'meta.binaries' => {};
191 # has 'meta.custom_data' => {};
193 has 'memory_protection.protect_title' => false
, coerce
=> \
&to_bool
;
194 has 'memory_protection.protect_username' => false
, coerce
=> \
&to_bool
;
195 has 'memory_protection.protect_password' => true
, coerce
=> \
&to_bool
;
196 has 'memory_protection.protect_url' => false
, coerce
=> \
&to_bool
;
197 has 'memory_protection.protect_notes' => false
, coerce
=> \
&to_bool
;
198 # has 'memory_protection.auto_enable_visual_hiding' => false;
201 HEADER_TRANSFORM_SEED
,
202 HEADER_TRANSFORM_ROUNDS
,
203 HEADER_INNER_RANDOM_STREAM_KEY
,
204 HEADER_INNER_RANDOM_STREAM_ID
,
205 HEADER_PUBLIC_CUSTOM_DATA
,
207 sub _set_nonlazy_attributes
{
209 $self->$_ for list_attributes
(ref $self), @ATTRS;
213 sub memory_protection
{
215 $self->{meta
}{memory_protection
} = shift if @_ == 1 && is_plain_hashref
($_[0]);
216 return $self->{meta
}{memory_protection
} //= {} if !@_;
218 my $string_key = shift;
219 my $key = 'protect_' . lc($string_key);
221 $self->meta->{memory_protection
}{$key} = shift if @_;
222 $self->meta->{memory_protection
}{$key};
226 sub minimum_version
{
229 return KDBX_VERSION_4_1
if any
{
230 nonempty
$_->{last_modification_time
}
231 } values %{$self->custom_data};
233 return KDBX_VERSION_4_1
if any
{
234 nonempty
$_->{name
} || nonempty
$_->{last_modification_time
}
235 } @{$self->custom_icons};
237 return KDBX_VERSION_4_1
if $self->groups->next(sub {
238 nonempty
$_->previous_parent_group ||
240 (any
{ nonempty
$_->{last_modification_time
} } values %{$_->custom_data})
243 return KDBX_VERSION_4_1
if $self->entries(history
=> 1)->next(sub {
244 nonempty
$_->previous_parent_group ||
245 (defined $_->quality_check && !$_->quality_check) ||
246 (any
{ nonempty
$_->{last_modification_time
} } values %{$_->custom_data})
249 return KDBX_VERSION_4_0
if $self->kdf->uuid ne KDF_UUID_AES
;
251 return KDBX_VERSION_4_0
if nonempty
$self->public_custom_data;
253 return KDBX_VERSION_4_0
if $self->objects->next(sub {
254 nonempty
$_->custom_data
257 return KDBX_VERSION_3_1
;
260 ##############################################################################
266 $self->{root
} = $self->_wrap_group(@_);
267 $self->{root
}->kdbx($self);
269 $self->{root
} //= $self->_implicit_root;
270 return $self->_wrap_group($self->{root
});
273 # Called by File::KeePass::KDBX so that a File::KDBX an be treated as a File::KDBX::Group in that both types
274 # can have subgroups. File::KDBX already has a `groups' method that does something different from the
275 # File::KDBX::Groups `groups' method.
278 return [] if !$self->{root
};
279 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
282 sub _has_implicit_root
{
284 my $root = $self->root;
285 my $temp = __PACKAGE__-
>_implicit_root;
286 # If an implicit root group has been changed in any significant way, it is no longer implicit.
287 return $root->name eq $temp->name &&
288 $root->is_expanded ^ $temp->is_expanded &&
289 $root->notes eq $temp->notes &&
290 !@{$root->entries} &&
291 !defined $root->custom_icon_uuid &&
292 !keys %{$root->custom_data} &&
293 $root->icon_id == $temp->icon_id &&
294 $root->expires ^ $temp->expires &&
295 $root->default_auto_type_sequence eq $temp->default_auto_type_sequence &&
296 !defined $root->enable_auto_type &&
297 !defined $root->enable_searching;
302 require File
::KDBX
::Group
;
303 return File
::KDBX
::Group-
>new(
306 notes
=> 'Added as an implicit root group by '.__PACKAGE__
.'.',
307 ref $self ? (kdbx
=> $self) : (),
315 return $object->lineage(@_);
323 push @lineage, $self->root if !@lineage;
324 my $base = $lineage[-1] or return [];
326 my $uuid = $object->uuid;
327 return \
@lineage if any
{ $_->uuid eq $uuid } @{$base->groups}, @{$base->entries};
329 for my $subgroup (@{$base->groups}) {
330 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
331 return $result if $result;
338 if (my $group = shift) {
339 $self->recycle_bin_uuid($group->uuid);
343 my $uuid = $self->recycle_bin_uuid;
344 $group = $self->groups->grep(uuid
=> $uuid)->next if $uuid ne UUID_NULL
;
345 if (!$group && $self->recycle_bin_enabled) {
346 $group = $self->add_group(
347 name
=> 'Recycle Bin',
348 icon_id
=> ICON_TRASHCAN_FULL
,
349 enable_auto_type
=> false
,
350 enable_searching
=> false
,
352 $self->recycle_bin_uuid($group->uuid);
358 sub entry_templates
{
360 if (my $group = shift) {
361 $self->entry_templates_group($group->uuid);
364 my $uuid = $self->entry_templates_group;
365 return if $uuid eq UUID_NULL
;
366 return $self->groups->grep(uuid
=> $uuid)->next;
372 if (my $group = shift) {
373 $self->last_selected_group($group->uuid);
376 my $uuid = $self->last_selected_group;
377 return if $uuid eq UUID_NULL
;
378 return $self->groups->grep(uuid
=> $uuid)->next;
382 sub last_top_visible
{
384 if (my $group = shift) {
385 $self->last_top_visible_group($group->uuid);
388 my $uuid = $self->last_top_visible_group;
389 return if $uuid eq UUID_NULL
;
390 return $self->groups->grep(uuid
=> $uuid)->next;
393 ##############################################################################
398 my $group = @_ % 2 == 1 ? shift : undef;
401 # find the right group to add the group to
402 my $parent = delete $args{group
} // delete $args{parent
} // $self->root;
403 $parent = $self->groups->grep({uuid
=> $parent})->next if !ref $parent;
404 $parent or throw
'Invalid group';
406 return $parent->add_group(defined $group ? $group : (), %args, kdbx
=> $self);
412 require File
::KDBX
::Group
;
413 return File
::KDBX
::Group-
>wrap($group, $self);
419 my %args = @_ % 2 == 0 ? @_ : (base
=> shift, @_);
420 my $base = delete $args{base
} // $self->root;
422 return $base->groups_deeply(%args);
425 ##############################################################################
430 my $entry = @_ % 2 == 1 ? shift : undef;
433 # find the right group to add the entry to
434 my $parent = delete $args{group
} // delete $args{parent
} // $self->root;
435 $parent = $self->groups->grep({uuid
=> $parent})->next if !ref $parent;
436 $parent or throw
'Invalid group';
438 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx
=> $self);
444 require File
::KDBX
::Entry
;
445 return File
::KDBX
::Entry-
>wrap($entry, $self);
451 my %args = @_ % 2 == 0 ? @_ : (base
=> shift, @_);
452 my $base = delete $args{base
} // $self->root;
454 return $base->entries_deeply(%args);
457 ##############################################################################
462 my %args = @_ % 2 == 0 ? @_ : (base
=> shift, @_);
463 my $base = delete $args{base
} // $self->root;
465 return $base->objects_deeply(%args);
468 sub __iter__
{ $_[0]->objects }
470 ##############################################################################
475 my %args = @_ == 2 ? (uuid
=> shift, data
=> shift)
476 : @_ % 2 == 1 ? (uuid
=> shift, @_) : @_;
478 if (!$args{uuid
} && !$args{data
}) {
479 my %standard = (uuid
=> 1, data
=> 1, name
=> 1, last_modification_time
=> 1);
480 my @other_keys = grep { !$standard{$_} } keys %args;
481 if (@other_keys == 1) {
482 my $key = $args{key
} = $other_keys[0];
483 $args{data
} = delete $args{$key};
487 my $uuid = $args{uuid
} or throw
'Must provide a custom icon UUID to access';
488 my $icon = (first
{ $_->{uuid
} eq $uuid } @{$self->custom_icons}) // do {
489 push @{$self->custom_icons}, my $i = { uuid
=> $uuid };
494 $fields = $args{data
} if is_plain_hashref
($args{data
});
496 while (my ($field, $value) = each %$fields) {
497 $icon->{$field} = $value;
503 sub custom_icon_data
{
505 my $uuid = shift // return;
506 my $icon = first
{ $_->{uuid
} eq $uuid } @{$self->custom_icons} or return;
507 return $icon->{data
};
511 sub add_custom_icon
{
513 my %args = @_ % 2 == 1 ? (data
=> shift, @_) : @_;
515 defined $args{data
} or throw
'Must provide image data';
517 my $uuid = $args{uuid
} // generate_uuid
;
518 push @{$self->custom_icons}, {
527 sub remove_custom_icon
{
531 @{$self->custom_icons} = grep { $_->{uuid
} eq $uuid ? do { push @deleted, $_; 0 } : 1 }
532 @{$self->custom_icons};
533 $self->add_deleted_object($uuid) if @deleted;
537 ##############################################################################
542 $self->{meta
}{custom_data
} = shift if @_ == 1 && is_plain_hashref
($_[0]);
543 return $self->{meta
}{custom_data
} //= {} if !@_;
545 my %args = @_ == 2 ? (key
=> shift, value
=> shift)
546 : @_ % 2 == 1 ? (key
=> shift, @_) : @_;
548 if (!$args{key
} && !$args{value
}) {
549 my %standard = (key
=> 1, value
=> 1, last_modification_time
=> 1);
550 my @other_keys = grep { !$standard{$_} } keys %args;
551 if (@other_keys == 1) {
552 my $key = $args{key
} = $other_keys[0];
553 $args{value
} = delete $args{$key};
557 my $key = $args{key
} or throw
'Must provide a custom_data key to access';
559 return $self->{meta
}{custom_data
}{$key} = $args{value
} if is_plain_hashref
($args{value
});
561 while (my ($field, $value) = each %args) {
562 $self->{meta
}{custom_data
}{$key}{$field} = $value;
564 return $self->{meta
}{custom_data
}{$key};
568 sub custom_data_value
{
570 my $data = $self->custom_data(@_) // return;
571 return $data->{value
};
575 sub public_custom_data
{
577 $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
} = shift if @_ == 1 && is_plain_hashref
($_[0]);
578 return $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
} //= {} if !@_;
580 my $key = shift or throw
'Must provide a public_custom_data key to access';
581 $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
}{$key} = shift if @_;
582 return $self->{headers
}{+HEADER_PUBLIC_CUSTOM_DATA
}{$key};
585 ##############################################################################
592 # my %options = @_; # prefer_old / prefer_new
593 # $other->merge_from($self);
600 # die 'Not implemented';
604 sub add_deleted_object
{
608 # ignore null and meta stream UUIDs
609 return if $uuid eq UUID_NULL
|| $uuid eq '0' x
16;
611 $self->deleted_objects->{$uuid} = {
613 deletion_time
=> scalar gmtime,
618 sub remove_deleted_object
{
621 delete $self->deleted_objects->{$uuid};
625 sub clear_deleted_objects
{
627 %{$self->deleted_objects} = ();
630 ##############################################################################
633 sub resolve_reference
{
635 my $wanted = shift // return;
636 my $search_in = shift;
639 if (!defined $text) {
640 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
641 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
643 $wanted && $search_in && nonempty
($text) or return;
647 U
=> 'expand_username',
648 P
=> 'expand_password',
652 O
=> 'other_strings',
654 $wanted = $fields{$wanted} or return;
655 $search_in = $fields{$search_in} or return;
657 my $query = $search_in eq 'uuid' ? query
($search_in => uuid
($text))
658 : simple_expression_query
($text, '=~', $search_in);
660 my $entry = $self->entries->grep($query)->next;
663 return $entry->$wanted;
666 our %PLACEHOLDERS = (
667 # 'PLACEHOLDER' => sub { my ($entry, $arg) = @_; ... };
668 'TITLE' => sub { $_[0]->expand_title },
669 'USERNAME' => sub { $_[0]->expand_username },
670 'PASSWORD' => sub { $_[0]->expand_password },
671 'NOTES' => sub { $_[0]->expand_notes },
672 'S:' => sub { $_[0]->string_value($_[1]) },
673 'URL' => sub { $_[0]->expand_url },
674 'URL:RMVSCM' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
675 'URL:WITHOUTSCHEME' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
676 'URL:SCM' => sub { (split_url
($_[0]->url))[0] },
677 'URL:SCHEME' => sub { (split_url
($_[0]->url))[0] }, # non-standard
678 'URL:HOST' => sub { (split_url
($_[0]->url))[2] },
679 'URL:PORT' => sub { (split_url
($_[0]->url))[3] },
680 'URL:PATH' => sub { (split_url
($_[0]->url))[4] },
681 'URL:QUERY' => sub { (split_url
($_[0]->url))[5] },
682 'URL:HASH' => sub { (split_url
($_[0]->url))[6] }, # non-standard
683 'URL:FRAGMENT' => sub { (split_url
($_[0]->url))[6] }, # non-standard
684 'URL:USERINFO' => sub { (split_url
($_[0]->url))[1] },
685 'URL:USERNAME' => sub { (split_url
($_[0]->url))[7] },
686 'URL:PASSWORD' => sub { (split_url
($_[0]->url))[8] },
687 'UUID' => sub { local $_ = format_uuid
($_[0]->uuid); s/-//g; $_ },
688 'REF:' => sub { $_[0]->kdbx->resolve_reference($_[1]) },
689 'INTERNETEXPLORER' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('iexplore') },
690 'FIREFOX' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('firefox') },
691 'GOOGLECHROME' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('google-chrome') },
692 'OPERA' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('opera') },
693 'SAFARI' => sub { load_optional
('IPC::Cmd'); IPC
::Cmd
::can_run
('safari') },
694 'APPDIR' => sub { load_optional
('FindBin'); $FindBin::Bin
},
695 'GROUP' => sub { my $p = $_[0]->group; $p ? $p->name : undef },
696 'GROUP_PATH' => sub { $_[0]->path },
697 'GROUP_NOTES' => sub { my $p = $_[0]->group; $p ? $p->notes : undef },
706 'ENV:' => sub { $ENV{$_[1]} },
707 'ENV_DIRSEP' => sub { load_optional
('File::Spec')->catfile('', '') },
708 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
711 'DT_SIMPLE' => sub { localtime-
>strftime('%Y%m%d%H%M%S') },
712 'DT_YEAR' => sub { localtime-
>strftime('%Y') },
713 'DT_MONTH' => sub { localtime-
>strftime('%m') },
714 'DT_DAY' => sub { localtime-
>strftime('%d') },
715 'DT_HOUR' => sub { localtime-
>strftime('%H') },
716 'DT_MINUTE' => sub { localtime-
>strftime('%M') },
717 'DT_SECOND' => sub { localtime-
>strftime('%S') },
718 'DT_UTC_SIMPLE' => sub { gmtime-
>strftime('%Y%m%d%H%M%S') },
719 'DT_UTC_YEAR' => sub { gmtime-
>strftime('%Y') },
720 'DT_UTC_MONTH' => sub { gmtime-
>strftime('%m') },
721 'DT_UTC_DAY' => sub { gmtime-
>strftime('%d') },
722 'DT_UTC_HOUR' => sub { gmtime-
>strftime('%H') },
723 'DT_UTC_MINUTE' => sub { gmtime-
>strftime('%M') },
724 'DT_UTC_SECOND' => sub { gmtime-
>strftime('%S') },
731 'HMACOTP' => sub { $_[0]->hmac_otp },
732 'TIMEOTP' => sub { $_[0]->time_otp },
733 'C:' => sub { '' }, # comment
741 ##############################################################################
746 $SAFE{$self} = shift if @_;
750 sub _remove_safe
{ delete $SAFE{$_[0]} }
755 $self->_safe and return $self;
759 $self->entries(history
=> 1)->each(sub {
760 push @strings, grep { $_->{protect
} } values %{$_->strings}, values %{$_->binaries};
763 $self->_safe(File
::KDBX
::Safe-
>new(\
@strings));
771 my $safe = $self->_safe or return $self;
781 throw
'Programmer error: Cannot call unlock_scoped in void context' if !defined wantarray;
783 return if !$self->is_locked;
784 require Scope
::Guard
;
785 my $guard = Scope
::Guard-
>new(sub { $self->lock });
794 my $safe = $self->_safe or return;
795 return $safe->peek($string);
799 sub is_locked
{ $_[0]->_safe ? 1 : 0 }
801 ##############################################################################
804 # - Fixer tool. Can repair inconsistencies, including:
805 # - Orphaned binaries... not really a thing anymore since we now distribute binaries amongst entries
806 # - Unused custom icons (OFF, data loss)
808 # - All data types are valid
809 # - date times are correct
811 # - All UUIDs refer to things that exist
812 # - previous parent group
814 # - last selected group
815 # - last visible group
816 # - Enforce history size limits (ON)
817 # - Check headers/meta (ON)
818 # - Duplicate deleted objects (ON)
819 # - Duplicate window associations (OFF)
820 # - Header UUIDs match known ciphers/KDFs?
824 sub remove_empty_groups
{
827 $self->groups(algorithm
=> 'dfs')
828 ->where(-true
=> 'is_empty')
829 ->each(sub { push @removed, $_->remove });
834 sub remove_unused_icons
{
836 my %icons = map { $_->{uuid
} => 0 } @{$self->custom_icons};
838 $self->objects->each(sub { ++$icons{$_->custom_icon_uuid // ''} });
841 push @removed, $self->remove_custom_icon($_) for grep { $icons{$_} == 0 } keys %icons;
846 sub remove_duplicate_icons
{
851 for my $icon (@{$self->custom_icons}) {
852 my $digest = digest_data
('SHA256', $icon->{data
});
853 if (my $other = $seen{$digest}) {
854 $dup{$icon->{uuid
}} = $other->{uuid
};
857 $seen{$digest} = $icon;
862 while (my ($old_uuid, $new_uuid) = each %dup) {
864 ->where(custom_icon_uuid
=> $old_uuid)
865 ->each(sub { $_->custom_icon_uuid($new_uuid) });
866 push @removed, $self->remove_custom_icon($old_uuid);
876 my $max_items = $args{max_items
} // $self->history_max_items // HISTORY_DEFAULT_MAX_ITEMS
;
877 my $max_size = $args{max_size
} // $self->history_max_size // HISTORY_DEFAULT_MAX_SIZE
;
878 my $max_age = $args{max_age
} // HISTORY_DEFAULT_MAX_AGE
;
881 $self->entries->each(sub {
882 push @removed, $_->prune_history(
883 max_items
=> $max_items,
884 max_size
=> $max_size,
892 sub randomize_seeds
{
894 $self->encryption_iv(random_bytes
(16));
895 $self->inner_random_stream_key(random_bytes
(64));
896 $self->master_seed(random_bytes
(32));
897 $self->stream_start_bytes(random_bytes
(32));
898 $self->transform_seed(random_bytes
(32));
901 ##############################################################################
906 $KEYS{$self} = File
::KDBX
::Key-
>new(@_) if @_;
913 require File
::KDBX
::Key
::Composite
;
914 return File
::KDBX
::Key
::Composite-
>new(@_);
920 my %args = @_ % 2 == 1 ? (params
=> shift, @_) : @_;
922 my $params = $args{params
};
923 my $compat = $args{compatible
} // 1;
925 $params //= $self->kdf_parameters;
926 $params = {%{$params || {}}};
928 if (empty
$params || !defined $params->{+KDF_PARAM_UUID
}) {
929 $params->{+KDF_PARAM_UUID
} = KDF_UUID_AES
;
931 if ($params->{+KDF_PARAM_UUID
} eq KDF_UUID_AES
) {
932 # AES_CHALLENGE_RESPONSE is equivalent to AES if there are no challenge-response keys, and since
933 # non-KeePassXC implementations don't support challenge-response keys anyway, there's no problem with
934 # always using AES_CHALLENGE_RESPONSE for all KDBX4+ databases.
935 # For compatibility, we should not *write* AES_CHALLENGE_RESPONSE, but the dumper handles that.
936 if ($self->version >= KDBX_VERSION_4_0
) {
937 $params->{+KDF_PARAM_UUID
} = KDF_UUID_AES_CHALLENGE_RESPONSE
;
939 $params->{+KDF_PARAM_AES_SEED
} //= $self->transform_seed;
940 $params->{+KDF_PARAM_AES_ROUNDS
} //= $self->transform_rounds;
943 require File
::KDBX
::KDF
;
944 return File
::KDBX
::KDF-
>new(%$params);
949 $self->headers->{+HEADER_TRANSFORM_SEED
} =
950 $self->headers->{+HEADER_KDF_PARAMETERS
}{+KDF_PARAM_AES_SEED
} = shift if @_;
951 $self->headers->{+HEADER_TRANSFORM_SEED
} =
952 $self->headers->{+HEADER_KDF_PARAMETERS
}{+KDF_PARAM_AES_SEED
} //= random_bytes
(32);
955 sub transform_rounds
{
957 $self->headers->{+HEADER_TRANSFORM_ROUNDS
} =
958 $self->headers->{+HEADER_KDF_PARAMETERS
}{+KDF_PARAM_AES_ROUNDS
} = shift if @_;
959 $self->headers->{+HEADER_TRANSFORM_ROUNDS
} =
960 $self->headers->{+HEADER_KDF_PARAMETERS
}{+KDF_PARAM_AES_ROUNDS
} //= 100_000;
968 $args{uuid
} //= $self->headers->{+HEADER_CIPHER_ID
};
969 $args{iv
} //= $self->headers->{+HEADER_ENCRYPTION_IV
};
971 require File
::KDBX
::Cipher
;
972 return File
::KDBX
::Cipher-
>new(%args);
980 $args{stream_id
} //= delete $args{id
} // $self->inner_random_stream_id;
981 $args{key
} //= $self->inner_random_stream_key;
983 require File
::KDBX
::Cipher
;
984 File
::KDBX
::Cipher-
>new(%args);
987 sub inner_random_stream_id
{
989 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID
}
990 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID
} = shift if @_;
991 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID
}
992 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID
} //= do {
993 my $version = $self->minimum_version;
994 $version < KDBX_VERSION_4_0
? STREAM_ID_SALSA20
: STREAM_ID_CHACHA20
;
998 sub inner_random_stream_key
{
1001 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1003 erase \
$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY
};
1004 erase \
$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY
};
1005 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY
}
1006 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY
} = shift;
1008 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY
}
1009 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY
} //= random_bytes
(64); # 32
1012 #########################################################################################
1014 sub _handle_signal
{
1020 'entry.added' => \
&_handle_object_added
,
1021 'group.added' => \
&_handle_object_added
,
1022 'entry.removed' => \
&_handle_object_removed
,
1023 'group.removed' => \
&_handle_object_removed
,
1024 'entry.uuid.changed' => \
&_handle_entry_uuid_changed
,
1025 'group.uuid.changed' => \
&_handle_group_uuid_changed
,
1027 my $handler = $handlers{$type} or return;
1028 $self->$handler($object, @_);
1031 sub _handle_object_added
{
1034 $self->remove_deleted_object($object->uuid);
1037 sub _handle_object_removed
{
1040 my $old_uuid = $object->{uuid
} // return;
1042 my $meta = $self->meta;
1043 $self->recycle_bin_uuid(UUID_NULL
) if $old_uuid eq ($meta->{recycle_bin_uuid
} // '');
1044 $self->entry_templates_group(UUID_NULL
) if $old_uuid eq ($meta->{entry_templates_group
} // '');
1045 $self->last_selected_group(UUID_NULL
) if $old_uuid eq ($meta->{last_selected_group
} // '');
1046 $self->last_top_visible_group(UUID_NULL
) if $old_uuid eq ($meta->{last_top_visible_group
} // '');
1048 $self->add_deleted_object($old_uuid);
1051 sub _handle_entry_uuid_changed
{
1054 my $new_uuid = shift;
1055 my $old_uuid = shift // return;
1057 my $old_pretty = format_uuid
($old_uuid);
1058 my $new_pretty = format_uuid
($new_uuid);
1059 my $fieldref_match = qr/\{REF:([TUPANI])\@I:\Q$old_pretty\E\}/is;
1061 $self->entries->each(sub {
1062 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group
} // '');
1064 for my $string (values %{$_->strings}) {
1065 next if !defined $string->{value
} || $string->{value
} !~ $fieldref_match;
1066 my $txn = $_->begin_work;
1067 $string->{value
} =~ s/$fieldref_match/{REF:$1\@I:$new_pretty}/g;
1073 sub _handle_group_uuid_changed
{
1076 my $new_uuid = shift;
1077 my $old_uuid = shift // return;
1079 my $meta = $self->meta;
1080 $self->recycle_bin_uuid($new_uuid) if $old_uuid eq ($meta->{recycle_bin_uuid
} // '');
1081 $self->entry_templates_group($new_uuid) if $old_uuid eq ($meta->{entry_templates_group
} // '');
1082 $self->last_selected_group($new_uuid) if $old_uuid eq ($meta->{last_selected_group
} // '');
1083 $self->last_top_visible_group($new_uuid) if $old_uuid eq ($meta->{last_top_visible_group
} // '');
1085 $self->groups->each(sub {
1086 $_->last_top_visible_entry($new_uuid) if $old_uuid eq ($_->{last_top_visible_entry
} // '');
1087 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group
} // '');
1089 $self->entries->each(sub {
1090 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group
} // '');
1094 #########################################################################################
1097 #########################################################################################
1099 sub TO_JSON
{ +{%{$_[0]}} }
1109 =for markdown [![Linux](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml)
1110 [![macOS](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml)
1111 [![Windows](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml)
1113 =for HTML <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>
1114 <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>
1115 <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>
1119 File::KDBX - Encrypted database to store secret text and files
1129 my $kdbx = File::KDBX->new;
1131 my $group = $kdbx->add_group(
1132 name => 'Passwords',
1135 my $entry = $group->add_entry(
1137 password => 's3cr3t',
1140 $kdbx->dump_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1142 $kdbx = File::KDBX->load_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1144 $kdbx->entries->each(sub {
1146 say 'Entry: ', $entry->title;
1149 See L</RECIPES> for more examples.
1153 B<File::KDBX> provides everything you need to work with a KDBX database. A KDBX database is a hierarchical
1154 object database which is commonly used to store secret information securely. It was developed for the KeePass
1155 password safe. See L</"Introduction to KDBX"> for more information about KDBX.
1157 This module lets you query entries, create new entries, delete entries and modify entries. The distribution
1158 also includes various parsers and generators for serializing and persisting databases.
1160 This design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
1161 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
1162 that works well in most cases but has a small backlog of bugs and security issues and also does not work with
1163 newer KDBX version 4 files. If you're coming here from the B<File::KeePass> world, you might be interested in
1164 L<File::KeePass::KDBX> that is a drop-in replacement for B<File::KeePass> that uses B<File::KDBX> for storage.
1166 This software is a B<pre-1.0 release>. The interface should be considered pretty stable, but there might be
1167 minor changes up until a 1.0 release. Breaking changes will be noted in the F<Changes> file.
1171 This implementation of KDBX supports a lot of features:
1177 ☑ Read and write KDBX version 3 - version 4.1
1181 ☑ Read and write KDB files (requires L<File::KeePass>)
1185 ☑ Unicode character strings
1189 ☑ L</"Simple Expression"> Searching
1193 ☑ L<Placeholders|File::KDBX::Entry/Placeholders> and L<field references|/resolve_reference>
1197 ☑ L<One-time passwords|File::KDBX::Entry/"One-time passwords">
1201 ☑ L<Very secure|/SECURITY>
1205 ☑ L</"Memory Protection">
1209 ☑ Challenge-response key components, like L<YubiKey|File::KDBX::Key::YubiKey>
1213 ☑ Variety of L<key file|File::KDBX::Key::File> types: binary, hexed, hashed, XML v1 and v2
1217 ☑ Pluggable registration of different kinds of ciphers and key derivation functions
1221 ☑ Built-in database maintenance functions
1225 ☑ Pretty fast, with L<XS optimizations|File::KDBX::XS> available
1229 ☒ Database synchronization / merging (not yet)
1233 =head2 Introduction to KDBX
1235 A KDBX database consists of a tree of I<groups> and I<entries>, with a single I<root> group. Entries can
1236 contain zero or more key-value pairs of I<strings> and zero or more I<binaries> (i.e. octet strings). Groups,
1237 entries, strings and binaries: that's the KDBX vernacular. A small amount of metadata (timestamps, etc.) is
1238 associated with each entry, group and the database as a whole.
1240 You can think of a KDBX database kind of like a file system, where groups are directories, entries are files,
1241 and strings and binaries make up a file's contents.
1243 Databases are typically persisted as a encrypted, compressed files. They are usually accessed directly (i.e.
1244 not over a network). The primary focus of this type of database is data security. It is ideal for storing
1245 relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as
1246 have the correct I<master key>. Even if the database file were to be "leaked" to the public Internet, it
1247 should be virtually impossible to crack with a strong key. The KDBX format is most often used by password
1248 managers to store passwords so that users can know a single strong password and not have to reuse passwords
1249 across different websites. See L</SECURITY> for an overview of security considerations.
1261 =head2 inner_headers
1267 =head2 deleted_objects
1269 Hash of UUIDs for objects that have been deleted. This includes groups, entries and even custom icons.
1273 Bytes contained within the encrypted layer of a KDBX file. This is only set when using
1274 L<File::KDBX::Loader::Raw>.
1278 A text string associated with the database. Often unset.
1282 The UUID of a cipher used to encrypt the database when stored as a file.
1284 See L</File::KDBX::Cipher>.
1286 =head2 compression_flags
1288 Configuration for whether or not and how the database gets compressed. See
1289 L<File::KDBX::Constants/":compression">.
1293 The master seed is a string of 32 random bytes that is used as salt in hashing the master key when loading
1294 and saving the database. If a challenge-response key is used in the master key, the master seed is also the
1297 The master seed I<should> be changed each time the database is saved to file.
1299 =head2 transform_seed
1301 The transform seed is a string of 32 random bytes that is used in the key derivation function, either as the
1302 salt or the key (depending on the algorithm).
1304 The transform seed I<should> be changed each time the database is saved to file.
1306 =head2 transform_rounds
1308 The number of rounds or iterations used in the key derivation function. Increasing this number makes loading
1309 and saving the database slower by design in order to make dictionary and brute force attacks more costly.
1311 =head2 encryption_iv
1313 The initialization vector used by the cipher.
1315 The encryption IV I<should> be changed each time the database is saved to file.
1317 =head2 inner_random_stream_key
1319 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1320 within the database.
1322 =head2 stream_start_bytes
1324 A string of 32 random bytes written in the header and encrypted in the body. If the bytes do not match when
1325 loading a file then the wrong master key was used or the file is corrupt. Only KDBX 2 and KDBX 3 files use
1326 this. KDBX 4 files use an improved HMAC method to verify the master key and data integrity of the header and
1329 =head2 inner_random_stream_id
1331 A number indicating the cipher algorithm used to encrypt the protected strings within the database, usually
1332 Salsa20 or ChaCha20. See L<File::KDBX::Constants/":random_stream">.
1334 =head2 kdf_parameters
1336 A hash/dict of key-value pairs used to configure the key derivation function. This is the KDBX4+ way to
1337 configure the KDF, superceding L</transform_seed> and L</transform_rounds>.
1341 The name of the software used to generate the KDBX file.
1345 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1347 =head2 database_name
1349 Name of the database.
1351 =head2 database_name_changed
1353 Timestamp indicating when the database name was last changed.
1355 =head2 database_description
1357 Description of the database
1359 =head2 database_description_changed
1361 Timestamp indicating when the database description was last changed.
1363 =head2 default_username
1365 When a new entry is created, the I<UserName> string will be populated with this value.
1367 =head2 default_username_changed
1369 Timestamp indicating when the default username was last changed.
1371 =head2 maintenance_history_days
1373 TODO... not really sure what this is. 😀
1377 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
1378 use this to help users visually distinguish between different databases.
1380 =head2 master_key_changed
1382 Timestamp indicating when the master key was last changed.
1384 =head2 master_key_change_rec
1386 Number of days until the agent should prompt to recommend changing the master key.
1388 =head2 master_key_change_force
1390 Number of days until the agent should prompt to force changing the master key.
1392 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
1393 C<File::KDBX> does NOT enforce it.
1397 Array of custom icons that can be associated with groups and entries.
1399 This list can be managed with the methods L</add_custom_icon> and L</remove_custom_icon>.
1401 =head2 recycle_bin_enabled
1403 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1405 =head2 recycle_bin_uuid
1407 The UUID of a group used to store thrown-away groups and entries.
1409 =head2 recycle_bin_changed
1411 Timestamp indicating when the recycle bin was last changed.
1413 =head2 entry_templates_group
1415 The UUID of a group containing template entries used when creating new entries.
1417 =head2 entry_templates_group_changed
1419 Timestamp indicating when the entry templates group was last changed.
1421 =head2 last_selected_group
1423 The UUID of the previously-selected group.
1425 =head2 last_top_visible_group
1427 The UUID of the group visible at the top of the list.
1429 =head2 history_max_items
1431 The maximum number of historical entries allowed to be saved for each entry.
1433 =head2 history_max_size
1435 The maximum total size (in bytes) that each individual entry's history is allowed to grow.
1437 =head2 settings_changed
1439 Timestamp indicating when the database settings were last updated.
1441 =head2 protect_title
1443 Alias of the L</memory_protection> setting for the I<Title> string.
1445 =head2 protect_username
1447 Alias of the L</memory_protection> setting for the I<UserName> string.
1449 =head2 protect_password
1451 Alias of the L</memory_protection> setting for the I<Password> string.
1455 Alias of the L</memory_protection> setting for the I<URL> string.
1457 =head2 protect_notes
1459 Alias of the L</memory_protection> setting for the I<Notes> string.
1465 $kdbx = File::KDBX->new(%attributes);
1466 $kdbx = File::KDBX->new($kdbx); # copy constructor
1468 Construct a new L<File::KDBX>.
1472 $kdbx = $kdbx->init(%attributes);
1474 Initialize a L<File::KDBX> with a set of attributes. Returns itself to allow method chaining.
1476 This is called by L</new>.
1480 $kdbx = $kdbx->reset;
1482 Set a L<File::KDBX> to an empty state, ready to load a KDBX file or build a new one. Returns itself to allow
1487 $kdbx_copy = $kdbx->clone;
1488 $kdbx_copy = File::KDBX->new($kdbx);
1490 Clone a L<File::KDBX>. The clone will be an exact copy and completely independent of the original.
1500 $kdbx = KDBX::File->load(\$string, $key);
1501 $kdbx = KDBX::File->load(*IO, $key);
1502 $kdbx = KDBX::File->load($filepath, $key);
1503 $kdbx->load(...); # also instance method
1505 $kdbx = File::KDBX->load_string($string, $key);
1506 $kdbx = File::KDBX->load_string(\$string, $key);
1507 $kdbx->load_string(...); # also instance method
1509 $kdbx = File::KDBX->load_file($filepath, $key);
1510 $kdbx->load_file(...); # also instance method
1512 $kdbx = File::KDBX->load_handle($fh, $key);
1513 $kdbx = File::KDBX->load_handle(*IO, $key);
1514 $kdbx->load_handle(...); # also instance method
1516 Load a KDBX file from a string buffer, IO handle or file from a filesystem.
1518 L<File::KDBX::Loader> does the heavy lifting.
1528 $kdbx->dump(\$string, $key);
1529 $kdbx->dump(*IO, $key);
1530 $kdbx->dump($filepath, $key);
1532 $kdbx->dump_string(\$string, $key);
1533 \$string = $kdbx->dump_string($key);
1535 $kdbx->dump_file($filepath, $key);
1537 $kdbx->dump_handle($fh, $key);
1538 $kdbx->dump_handle(*IO, $key);
1540 Dump a KDBX file to a string buffer, IO handle or file in a filesystem.
1542 L<File::KDBX::Dumper> does the heavy lifting.
1544 =head2 user_agent_string
1546 $string = $kdbx->user_agent_string;
1548 Get a text string identifying the database client software.
1550 =head2 memory_protection
1552 \%settings = $kdbx->memory_protection
1553 $kdbx->memory_protection(\%settings);
1555 $bool = $kdbx->memory_protection($string_key);
1556 $kdbx->memory_protection($string_key => $bool);
1558 Get or set memory protection settings. This globally (for the whole database) configures whether and which of
1559 the standard strings should be memory-protected. The default setting is to memory-protect only I<Password>
1562 Memory protection can be toggled individually for each entry string, and individual settings take precedence
1563 over these global settings.
1565 =head2 minimum_version
1567 $version = $kdbx->minimum_version;
1569 Determine the minimum file version required to save a database losslessly. Using certain databases features
1570 might increase this value. For example, setting the KDF to Argon2 will increase the minimum version to at
1571 least C<KDBX_VERSION_4_0> (i.e. C<0x00040000>) because Argon2 was introduced with KDBX4.
1573 This method never returns less than C<KDBX_VERSION_3_1> (i.e. C<0x00030001>). That file version is so
1574 ubiquitious and well-supported, there are seldom reasons to dump in a lesser format nowadays.
1576 B<WARNING:> If you dump a database with a minimum version higher than the current L</version>, the dumper will
1577 typically issue a warning and automatically upgrade the database. This seems like the safest behavior in order
1578 to avoid data loss, but lower versions have the benefit of being compatible with more software. It is possible
1579 to prevent auto-upgrades by explicitly telling the dumper which version to use, but you do run the risk of
1580 data loss. A database will never be automatically downgraded.
1584 $group = $kdbx->root;
1585 $kdbx->root($group);
1587 Get or set a database's root group. You don't necessarily need to explicitly create or set a root group
1588 because it autovivifies when adding entries and groups to the database.
1590 Every database has only a single root group at a time. Some old KDB files might have multiple root groups.
1591 When reading such files, a single implicit root group is created to contain the actual root groups. When
1592 writing to such a format, if the root group looks like it was implicitly created then it won't be written and
1593 the resulting file might have multiple root groups. This allows working with older files without changing
1594 their written internal structure while still adhering to modern semantics while the database is opened.
1596 The root group of a KDBX database contains all of the database's entries and other groups. If you replace the
1597 root group, you are essentially replacing the entire database contents with something else.
1599 =head2 trace_lineage
1601 \@lineage = $kdbx->trace_lineage($group);
1602 \@lineage = $kdbx->trace_lineage($group, $base_group);
1603 \@lineage = $kdbx->trace_lineage($entry);
1604 \@lineage = $kdbx->trace_lineage($entry, $base_group);
1606 Get the direct line of ancestors from C<$base_group> (default: the root group) to a group or entry. The
1607 lineage includes the base group but I<not> the target group or entry. Returns C<undef> if the target is not in
1608 the database structure.
1612 $group = $kdbx->recycle_bin;
1613 $kdbx->recycle_bin($group);
1615 Get or set the recycle bin group. Returns C<undef> if there is no recycle bin and L</recycle_bin_enabled> is
1616 false, otherwise the current recycle bin or an autovivified recycle bin group is returned.
1618 =head2 entry_templates
1620 $group = $kdbx->entry_templates;
1621 $kdbx->entry_templates($group);
1623 Get or set the entry templates group. May return C<undef> if unset.
1625 =head2 last_selected
1627 $group = $kdbx->last_selected;
1628 $kdbx->last_selected($group);
1630 Get or set the last selected group. May return C<undef> if unset.
1632 =head2 last_top_visible
1634 $group = $kdbx->last_top_visible;
1635 $kdbx->last_top_visible($group);
1637 Get or set the last top visible group. May return C<undef> if unset.
1641 $kdbx->add_group($group);
1642 $kdbx->add_group(%group_attributes, %options);
1644 Add a group to a database. This is equivalent to identifying a parent group and calling
1645 L<File::KDBX::Group/add_group> on the parent group, forwarding the arguments. Available options:
1651 C<group> (aka C<parent>) - Group object or group UUID to add the group to (default: root group)
1657 \&iterator = $kdbx->groups(%options);
1658 \&iterator = $kdbx->groups($base_group, %options);
1660 Get an L<File::KDBX::Iterator> over I<groups> within a database. Options:
1666 C<base> - Only include groups within a base group (same as C<$base_group>) (default: L</root>)
1670 C<inclusive> - Include the base group in the results (default: true)
1674 C<algorithm> - Search algorithm, one of C<ids>, C<bfs> or C<dfs> (default: C<ids>)
1680 $kdbx->add_entry($entry, %options);
1681 $kdbx->add_entry(%entry_attributes, %options);
1683 Add a entry to a database. This is equivalent to identifying a parent group and calling
1684 L<File::KDBX::Group/add_entry> on the parent group, forwarding the arguments. Available options:
1690 C<group> (aka C<parent>) - Group object or group UUID to add the entry to (default: root group)
1696 \&iterator = $kdbx->entries(%options);
1697 \&iterator = $kdbx->entries($base_group, %options);
1699 Get an L<File::KDBX::Iterator> over I<entries> within a database. Supports the same options as L</groups>,
1706 C<auto_type> - Only include entries with auto-type enabled (default: false, include all)
1710 C<searching> - Only include entries within groups with searching enabled (default: false, include all)
1714 C<history> - Also include historical entries (default: false, include only current entries)
1720 \&iterator = $kdbx->objects(%options);
1721 \&iterator = $kdbx->objects($base_group, %options);
1723 Get an L<File::KDBX::Iterator> over I<objects> within a database. Groups and entries are considered objects,
1724 so this is essentially a combination of L</groups> and L</entries>. This won't often be useful, but it can be
1725 convenient for maintenance tasks. This method takes the same options as L</groups> and L</entries>.
1729 \%icon = $kdbx->custom_icon($uuid);
1730 $kdbx->custom_icon($uuid => \%icon);
1731 $kdbx->custom_icon(%icon);
1732 $kdbx->custom_icon(uuid => $value, %icon);
1734 Get or set custom icons.
1736 =head2 custom_icon_data
1738 $image_data = $kdbx->custom_icon_data($uuid);
1740 Get a custom icon image data.
1742 =head2 add_custom_icon
1744 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
1745 $uuid = $kdbx->add_custom_icon(%attributes);
1747 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
1753 C<uuid> - Icon UUID (default: autogenerated)
1757 C<data> - Image data (same as C<$image_data>)
1761 C<name> - Name of the icon (text, KDBX4.1+)
1765 C<last_modification_time> - Just what it says (datetime, KDBX4.1+)
1769 =head2 remove_custom_icon
1771 $kdbx->remove_custom_icon($uuid);
1773 Remove a custom icon.
1777 \%all_data = $kdbx->custom_data;
1778 $kdbx->custom_data(\%all_data);
1780 \%data = $kdbx->custom_data($key);
1781 $kdbx->custom_data($key => \%data);
1782 $kdbx->custom_data(%data);
1783 $kdbx->custom_data(key => $value, %data);
1785 Get and set custom data. Custom data is metadata associated with a database.
1787 Each data item can have a few attributes associated with it.
1793 C<key> - A unique text string identifier used to look up the data item (required)
1797 C<value> - A text string value (required)
1801 C<last_modification_time> (optional, KDBX4.1+)
1805 =head2 custom_data_value
1807 $value = $kdbx->custom_data_value($key);
1809 Exactly the same as L</custom_data> except returns just the custom data's value rather than a structure of
1810 attributes. This is a shortcut for:
1812 my $data = $kdbx->custom_data($key);
1813 my $value = defined $data ? $data->{value} : undef;
1815 =head2 public_custom_data
1817 \%all_data = $kdbx->public_custom_data;
1818 $kdbx->public_custom_data(\%all_data);
1820 $value = $kdbx->public_custom_data($key);
1821 $kdbx->public_custom_data($key => $value);
1823 Get and set public custom data. Public custom data is similar to custom data but different in some important
1824 ways. Public custom data:
1830 can store strings, booleans and up to 64-bit integer values (custom data can only store text values)
1834 is NOT encrypted within a KDBX file (hence the "public" part of the name)
1838 is a plain hash/dict of key-value pairs with no other associated fields (like modification times)
1842 =head2 add_deleted_object
1844 $kdbx->add_deleted_object($uuid);
1846 Add a UUID to the deleted objects list. This list is used to support automatic database merging.
1848 You typically do not need to call this yourself because the list will be populated automatically as objects
1851 =head2 remove_deleted_object
1853 $kdbx->remove_deleted_object($uuid);
1855 Remove a UUID from the deleted objects list. This list is used to support automatic database merging.
1857 You typically do not need to call this yourself because the list will be maintained automatically as objects
1860 =head2 clear_deleted_objects
1862 Remove all UUIDs from the deleted objects list. This list is used to support automatic database merging, but
1863 if you don't need merging then you can clear deleted objects to reduce the database file size.
1865 =head2 resolve_reference
1867 $string = $kdbx->resolve_reference($reference);
1868 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
1870 Resolve a L<field reference|https://keepass.info/help/base/fieldrefs.html>. A field reference is a kind of
1871 string placeholder. You can use a field reference to refer directly to a standard field within an entry. Field
1872 references are resolved automatically while expanding entry strings (i.e. replacing placeholders), but you can
1873 use this method to resolve on-the-fly references that aren't part of any actual string in the database.
1875 If the reference does not resolve to any field, C<undef> is returned. If the reference resolves to multiple
1876 fields, only the first one is returned (in the same order as iterated by L</entries>). To avoid ambiguity, you
1877 can refer to a specific entry by its UUID.
1879 The syntax of a reference is: C<< {REF:<WantedField>@<SearchIn>:<Text>} >>. C<Text> is a
1880 L</"Simple Expression">. C<WantedField> and C<SearchIn> are both single character codes representing a field:
1910 C<O> - Other custom strings
1914 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
1918 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
1920 my $username = $kdbx->resolve_reference('{REF:U@T:"My Bank"}');
1921 # OR the {REF:...} wrapper is optional
1922 my $username = $kdbx->resolve_reference('U@T:"My Bank"');
1923 # OR separate the arguments
1924 my $username = $kdbx->resolve_reference(U => T => '"My Bank"');
1926 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
1929 To get the I<Password> string of a specific entry (identified by its UUID):
1931 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
1937 Encrypt all protected binaries strings in a database. The encrypted strings are stored in
1938 a L<File::KDBX::Safe> associated with the database and the actual strings will be replaced with C<undef> to
1939 indicate their protected state. Returns itself to allow method chaining.
1941 You can call C<code> on an already-locked database to memory-protect any unprotected strings and binaries
1942 added after the last time the database was locked.
1948 Decrypt all protected strings in a database, replacing C<undef> placeholders with unprotected values. Returns
1949 itself to allow method chaining.
1951 =head2 unlock_scoped
1953 $guard = $kdbx->unlock_scoped;
1955 Unlock a database temporarily, relocking when the guard is released (typically at the end of a scope). Returns
1956 C<undef> if the database is already unlocked.
1958 See L</lock> and L</unlock>.
1962 $string = $kdbx->peek(\%string);
1963 $string = $kdbx->peek(\%binary);
1965 Peek at the value of a protected string or binary without unlocking the whole database. The argument can be
1966 a string or binary hashref as returned by L<File::KDBX::Entry/string> or L<File::KDBX::Entry/binary>.
1970 $bool = $kdbx->is_locked;
1972 Get whether or not a database's strings are memory-protected. If this is true, then some or all of the
1973 protected strings within the database will be unavailable (literally have C<undef> values) until L</unlock> is
1976 =head2 remove_empty_groups
1978 $kdbx->remove_empty_groups;
1980 Remove groups with no subgroups and no entries.
1982 =head2 remove_unused_icons
1984 $kdbx->remove_unused_icons;
1986 Remove icons that are not associated with any entry or group in the database.
1988 =head2 remove_duplicate_icons
1990 $kdbx->remove_duplicate_icons;
1992 Remove duplicate icons as determined by hashing the icon data.
1994 =head2 prune_history
1996 $kdbx->prune_history(%options);
1998 Remove just as many older historical entries as necessary to get under certain limits.
2004 C<max_items> - Maximum number of historical entries to keep (default: value of L</history_max_items>, no limit: -1)
2008 C<max_size> - Maximum total size (in bytes) of historical entries to keep (default: value of L</history_max_size>, no limit: -1)
2012 C<max_age> - Maximum age (in days) of historical entries to keep (default: 365, no limit: -1)
2016 =head2 randomize_seeds
2018 $kdbx->randomize_seeds;
2020 Set various keys, seeds and IVs to random values. These values are used by the cryptographic functions that
2021 secure the database when dumped. The attributes that will be randomized are:
2031 L</inner_random_stream_key>
2039 L</stream_start_bytes>
2047 Randomizing these values has no effect on a loaded database. These are only used when a database is dumped.
2048 You normally do not need to call this method explicitly because the dumper does it explicitly by default.
2053 $key = $kdbx->key($key);
2054 $key = $kdbx->key($primitive);
2056 Get or set a L<File::KDBX::Key>. This is the master key (e.g. a password or a key file that can decrypt
2057 a database). See L<File::KDBX::Key/new> for an explanation of what the primitive can be.
2059 You generally don't need to call this directly because you can provide the key directly to the loader or
2060 dumper when loading or dumping a KDBX file.
2062 =head2 composite_key
2064 $key = $kdbx->composite_key($key);
2065 $key = $kdbx->composite_key($primitive);
2067 Construct a L<File::KDBX::Key::Composite> from a primitive. See L<File::KDBX::Key/new> for an explanation of
2068 what the primitive can be. If the primitive does not represent a composite key, it will be wrapped.
2070 You generally don't need to call this directly. The parser and writer use it to transform a master key into
2071 a raw encryption key.
2075 $kdf = $kdbx->kdf(%options);
2076 $kdf = $kdbx->kdf(\%parameters, %options);
2078 Get a L<File::KDBX::KDF> (key derivation function).
2086 C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
2092 $cipher = $kdbx->cipher(key => $key);
2093 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
2095 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
2097 A key is required. This should be a raw encryption key made up of a fixed number of octets (depending on the
2098 cipher), not a L<File::KDBX::Key> or primitive.
2100 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
2101 C<< $kdbx->headers->{encryption_iv} >>.
2103 You generally don't need to call this directly. The parser and writer use it to decrypt and encrypt KDBX
2106 =head2 random_stream
2108 $cipher = $kdbx->random_stream;
2109 $cipher = $kdbx->random_stream(id => $stream_id, key => $key);
2111 Get a L<File::KDBX::Cipher::Stream> for decrypting and encrypting protected values.
2113 If not passed, the ID and encryption key comes from C<< $kdbx->headers->{inner_random_stream_id} >> and
2114 C<< $kdbx->headers->{inner_random_stream_key} >> (respectively) for KDBX3 files and from
2115 C<< $kdbx->inner_headers->{inner_random_stream_key} >> and
2116 C<< $kdbx->inner_headers->{inner_random_stream_id} >> (respectively) for KDBX4 files.
2118 You generally don't need to call this directly. The parser and writer use it to scramble protected strings.
2120 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
2124 =head2 Create a new database
2126 my $kdbx = File::KDBX->new;
2128 my $group = $kdbx->add_group(name => 'Passwords);
2129 my $entry = $group->add_entry(
2130 title => 'WayneCorp',
2131 username => 'bwayne',
2132 password => 'iambatman',
2133 url => 'https://example.com/login'
2135 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
2137 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
2139 =head2 Read an existing database
2141 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
2142 $kdbx->unlock; # cause $entry->password below to be defined
2144 $kdbx->entries->each(sub {
2146 say 'Found password for: ', $entry->title;
2147 say ' Username: ', $entry->username;
2148 say ' Password: ', $entry->password;
2151 =head2 Search for entries
2153 my @entries = $kdbx->entries(searching => 1)
2154 ->grep(title => 'WayneCorp')
2155 ->each; # return all matches
2157 The C<searching> option limits results to only entries within groups with searching enabled. Other options are
2158 also available. See L</entries>.
2160 See L</QUERY> for many more query examples.
2162 =head2 Search for entries by auto-type window association
2164 my $window_title = 'WayneCorp - Mozilla Firefox';
2166 my $entries = $kdbx->entries(auto_type => 1)
2168 my ($ata) = grep { $_->{window} =~ /\Q$window_title\E/i } @{$_->auto_type_associations};
2169 return [$_, $ata->{keystroke_sequence}] if $ata;
2172 my ($entry, $keys) = @$_;
2173 say 'Entry title: ', $entry->title, ', key sequence: ', $keys;
2178 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
2180 =head2 Remove entries from a database
2183 ->grep(notes => {'=~' => qr/too old/i})
2184 ->each(sub { $_->recycle });
2186 Recycle all entries with the string "too old" appearing in the B<Notes> string.
2188 =head2 Remove empty groups
2190 $kdbx->groups(algorithm => 'dfs')
2191 ->where(-true => 'is_empty')
2194 With the search/iteration C<algorithm> set to "dfs", groups will be ordered deepest first and the root group
2195 will be last. This allows removing groups that only contain empty groups.
2197 This can also be done with one call to L</remove_empty_groups>.
2201 One of the biggest threats to your database security is how easily the encryption key can be brute-forced.
2202 Strong brute-force protection depends on:
2208 Using unguessable passwords, passphrases and key files.
2212 Using a brute-force resistent key derivation function.
2216 The first factor is up to you. This module does not enforce strong master keys. It is up to you to pick or
2217 generate strong keys.
2219 The KDBX format allows for the key derivation function to be tuned. The idea is that you want each single
2220 brute-foce attempt to be expensive (in terms of time, CPU usage or memory usage), so that making a lot of
2221 attempts (which would be required if you have a strong master key) gets I<really> expensive.
2223 How expensive you want to make each attempt is up to you and can depend on the application.
2225 This and other KDBX-related security issues are covered here more in depth:
2226 L<https://keepass.info/help/base/security.html>
2228 Here are other security risks you should be thinking about:
2232 This distribution uses the excellent L<CryptX> and L<Crypt::Argon2> packages to handle all crypto-related
2233 functions. As such, a lot of the security depends on the quality of these dependencies. Fortunately these
2234 modules are maintained and appear to have good track records.
2236 The KDBX format has evolved over time to incorporate improved security practices and cryptographic functions.
2237 This package uses the following functions for authentication, hashing, encryption and random number
2280 At the time of this writing, I am not aware of any successful attacks against any of these functions. These
2281 are among the most-analyzed and widely-adopted crypto functions available.
2283 The KDBX format allows the body cipher and key derivation function to be configured. If a flaw is discovered
2284 in one of these functions, you can hopefully just switch to a better function without needing to update this
2285 software. A later software release may phase out the use of any functions which are no longer secure.
2287 =head2 Memory Protection
2289 It is not a good idea to keep secret information unencrypted in system memory for longer than is needed. The
2290 address space of your program can generally be read by a user with elevated privileges on the system. If your
2291 system is memory-constrained or goes into a hibernation mode, the contents of your address space could be
2292 written to a disk where it might be persisted for long time.
2294 There might be system-level things you can do to reduce your risk, like using swap encryption and limiting
2295 system access to your program's address space while your program is running.
2297 B<File::KDBX> helps minimize (but not eliminate) risk by keeping secrets encrypted in memory until accessed
2298 and zeroing out memory that holds secrets after they're no longer needed, but it's not a silver bullet.
2300 For one thing, the encryption key is stored in the same address space. If core is dumped, the encryption key
2301 is available to be found out. But at least there is the chance that the encryption key and the encrypted
2302 secrets won't both be paged out together while memory-constrained.
2304 Another problem is that some perls (somewhat notoriously) copy around memory behind the scenes willy nilly,
2305 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
2306 be impossible. The good news is that perls with SvPV copy-on-write (enabled by default beginning with perl
2307 5.20) are much better in this regard. With COW, it's mostly possible to know what operations will cause perl
2308 to copy the memory of a scalar string, and the number of copies will be significantly reduced. There is a unit
2309 test named F<t/memory-protection.t> in this distribution that can be run on POSIX systems to determine how
2310 well B<File::KDBX> memory protection is working.
2312 Memory protection also depends on how your application handles secrets. If your app code is handling scalar
2313 strings with secret information, it's up to you to make sure its memory is zeroed out when no longer needed.
2314 L<File::KDBX::Util/erase> et al. provide some tools to help accomplish this. Or if you're not too concerned
2315 about the risks memory protection is meant to mitigate, then maybe don't worry about it. The security policy
2316 of B<File::KDBX> is to try hard to keep secrets protected while in memory so that your app might claim a high
2317 level of security, in case you care about that.
2319 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
2321 Many systems allow programs to mark unswappable pages. Secret information should ideally be stored in such
2322 pages. You could potentially use L<mlockall(2)> (or equivalent for your system) in your own application to
2323 prevent the entire address space from being swapped.
2325 Some systems provide special syscalls for storing secrets in memory while keeping the encryption key outside
2326 of the program's address space, like C<CryptProtectMemory> for Windows. This could be a good option, though
2327 unfortunately not portable.
2331 To find things in a KDBX database, you should use a filtered iterator. If you have an iterator, such as
2332 returned by L</entries>, L</groups> or even L</objects> you can filter it using L<File::KDBX::Iterator/where>.
2334 my $filtered_entries = $kdbx->entries->where($query);
2336 A C<$query> is just a subroutine that you can either write yourself or have generated for you from either
2337 a L</"Simple Expression"> or L</"Declarative Syntax">. It's easier to have your query generated, so I'll cover
2340 =head2 Simple Expression
2342 A simple expression is mostly compatible with the KeePass 2 implementation
2343 L<described here|https://keepass.info/help/base/search.html#mode_se>.
2345 An expression is a string with one or more space-separated terms. Terms with spaces can be enclosed in double
2346 quotes. Terms are negated if they are prefixed with a minus sign. A record must match every term on at least
2347 one of the given fields.
2349 So a simple expression is something like what you might type into a search engine. You can generate a simple
2350 expression query using L<File::KDBX::Util/simple_expression_query> or by passing the simple expression as
2351 a B<scalar reference> to C<where>.
2353 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
2355 my $entries = $kdbx->entries->where(\'canyon', qw[title]);
2357 Notice the first argument is a B<scalarref>. This disambiguates a simple expression from other types of
2358 queries covered below.
2360 As mentioned, a simple expression can have multiple terms. This simple expression query matches any entry that
2361 has the words "red" B<and> "canyon" anywhere in the title:
2363 my $entries = $kdbx->entries->where(\'red canyon', qw[title]);
2365 Each term in the simple expression must be found for an entry to match.
2367 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
2369 my $entries = $kdbx->entries->where(\'red -canyon', qw[title]);
2371 To search over multiple fields simultaneously, just list them all. To search for entries with "grocery" (but
2372 not "Foodland") in the title or notes:
2374 my $entries = $kdbx->entries->where(\'grocery -Foodland', qw[title notes]);
2376 The default operator is a case-insensitive regexp match, which is fine for searching text loosely. You can use
2377 just about any binary comparison operator that perl supports. To specify an operator, list it after the simple
2378 expression. For example, to search for any entry that has been used at least five times:
2380 my $entries = $kdbx->entries->where(\5, '>=', qw[usage_count]);
2382 It helps to read it right-to-left, like "usage_count is greater than or equal to 5".
2384 If you find the disambiguating structures to be distracting or confusing, you can also the
2385 L<File::KDBX::Util/simple_expression_query> function as a more intuitive alternative. The following example is
2386 equivalent to the previous:
2388 my $entries = $kdbx->entries->where(simple_expression_query(5, '>=', qw[usage_count]));
2390 =head2 Declarative Syntax
2392 Structuring a declarative query is similar to L<SQL::Abstract/"WHERE CLAUSES">, but you don't have to be
2393 familiar with that module. Just learn by examples here.
2395 To search for all entries in a database titled "My Bank":
2397 my $entries = $kdbx->entries->where({ title => 'My Bank' });
2399 The query here is C<< { title => 'My Bank' } >>. A hashref can contain key-value pairs where the key is an
2400 attribute of the thing being searched for (in this case an entry) and the value is what you want the thing's
2401 attribute to be to consider it a match. In this case, the attribute we're using as our match criteria is
2402 L<File::KDBX::Entry/title>, a text field. If an entry has its title attribute equal to "My Bank", it's
2405 A hashref can contain multiple attributes. The search candidate will be a match if I<all> of the specified
2406 attributes are equal to their respective values. For example, to search for all entries with a particular URL
2409 my $entries = $kdbx->entries->where({
2410 url => 'https://example.com',
2414 To search for entries matching I<any> criteria, just change the hashref to an arrayref. To search for entries
2415 with a particular URL B<OR> username:
2417 my $entries = $kdbx->entries->where([ # <-- Notice the square bracket
2418 url => 'https://example.com',
2422 You can use different operators to test different types of attributes. The L<File::KDBX::Entry/icon_id>
2423 attribute is a number, so we should use a number comparison operator. To find entries using the smartphone
2426 my $entries = $kdbx->entries->where({
2427 icon_id => { '==', ICON_SMARTPHONE },
2430 Note: L<File::KDBX::Constants/ICON_SMARTPHONE> is just a constant from L<File::KDBX::Constants>. It isn't
2431 special to this example or to queries generally. We could have just used a literal number.
2433 The important thing to notice here is how we wrapped the condition in another arrayref with a single key-value
2434 pair where the key is the name of an operator and the value is the thing to match against. The supported
2441 C<eq> - String equal
2445 C<ne> - String not equal
2449 C<lt> - String less than
2453 C<gt> - String greater than
2457 C<le> - String less than or equal
2461 C<ge> - String greater than or equal
2465 C<==> - Number equal
2469 C<!=> - Number not equal
2473 C<< < >> - Number less than
2477 C<< > >>> - Number greater than
2481 C<< <= >> - Number less than or equal
2485 C<< >= >> - Number less than or equal
2489 C<=~> - String match regular expression
2493 C<!~> - String does not match regular expression
2497 C<!> - Boolean false
2501 C<!!> - Boolean true
2505 Other special operators:
2511 C<-true> - Boolean true
2515 C<-false> - Boolean false
2519 C<-not> - Boolean false (alias for C<-false>)
2523 C<-defined> - Is defined
2527 C<-undef> - Is not defined
2531 C<-empty> - Is empty
2535 C<-nonempty> - Is not empty
2543 C<-and> - Logical and
2547 Let's see another example using an explicit operator. To find all groups except one in particular (identified
2548 by its L<File::KDBX::Group/uuid>), we can use the C<ne> (string not equal) operator:
2550 my $groups = $kdbx->groups->where(
2552 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
2556 Note: L<File::KDBX::Util/uuid> is a little utility function to convert a UUID in its pretty form into bytes.
2557 This utility function isn't special to this example or to queries generally. It could have been written with
2558 a literal such as C<"\x59\x6f\x75\x20\x61...">, but that's harder to read.
2560 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2562 Notice also that we didn't wrap the query in hashref curly-braces or arrayref square-braces. Those are
2563 optional. By default it will only match ALL attributes (as if there were curly-braces).
2565 Testing the truthiness of an attribute is a little bit different because it isn't a binary operation. To find
2566 all entries with the password quality check disabled:
2568 my $entries = $kdbx->entries->where('!' => 'quality_check');
2570 This time the string after the operator is the attribute name rather than a value to compare the attribute
2571 against. To test that a boolean value is true, use the C<!!> operator (or C<-true> if C<!!> seems a little too
2572 weird for your taste):
2574 my $entries = $kdbx->entries->where('!!' => 'quality_check');
2575 my $entries = $kdbx->entries->where(-true => 'quality_check'); # same thing
2577 Yes, there is also a C<-false> and a C<-not> if you prefer one of those over C<!>. C<-false> and C<-not>
2578 (along with C<-true>) are also special in that you can use them to invert the logic of a subquery. These are
2579 logically equivalent:
2581 my $entries = $kdbx->entries->where(-not => { title => 'My Bank' });
2582 my $entries = $kdbx->entries->where(title => { 'ne' => 'My Bank' });
2584 These special operators become more useful when combined with two more special operators: C<-and> and C<-or>.
2585 With these, it is possible to construct more interesting queries with groups of logic. For example:
2587 my $entries = $kdbx->entries->where({
2588 title => { '=~', qr/bank/ },
2591 notes => { '=~', qr/business/ },
2592 icon_id => { '==', ICON_TRASHCAN_FULL },
2597 In English, find entries where the word "bank" appears anywhere in the title but also do not have either the
2598 word "business" in the notes or are using the full trashcan icon.
2600 =head2 Subroutine Query
2602 Lastly, as mentioned at the top, you can ignore all this and write your own subroutine. Your subroutine will
2603 be called once for each object being searched over. The subroutine should match the candidate against whatever
2604 criteria you want and return true if it matches or false to skip. To do this, just pass your subroutine
2605 coderef to C<where>.
2607 To review the different types of queries, these are all equivalent to find all entries in the database titled
2610 my $entries = $kdbx->entries->where(\'"My Bank"', 'eq', qw[title]); # simple expression
2611 my $entries = $kdbx->entries->where(title => 'My Bank'); # declarative syntax
2612 my $entries = $kdbx->entries->where(sub { $_->title eq 'My Bank' }); # subroutine query
2614 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2616 All of these query mechanisms described in this section are just tools, each with its own set of limitations.
2617 If the tools are getting in your way, you can of course iterate over the contents of a database and implement
2618 your own query logic, like this:
2620 my $entries = $kdbx->entries;
2621 while (my $entry = $entries->next) {
2622 if (wanted($entry)) {
2623 do_something($entry);
2632 Iterators are the built-in way to navigate or walk the database tree. You get an iterator from L</entries>,
2633 L</groups> and L</objects>. You can specify the search algorithm to iterate over objects in different orders
2634 using the C<algorith> option, which can be one of these L<constants|File::KDBX::Constants/":iteration">:
2640 C<ITERATION_IDS> - Iterative deepening search (default)
2644 C<ITERATION_DFS> - Depth-first search
2648 C<ITERATION_BFS> - Breadth-first search
2652 When iterating over objects generically, groups always precede their direct entries (if any). When the
2653 C<history> option is used, current entries always precede historical entries.
2655 If you have a database tree like this:
2666 IDS order of groups is: Root, Group1, Group2, Group3
2667 IDS order of entries is: EntryA, EntryB, EntryC
2668 IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC
2670 DFS order of groups is: Group2, Group1, Group3, Root
2671 DFS order of entries is: EntryB, EntryA, EntryC
2672 DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root
2674 BFS order of groups is: Root, Group1, Group3, Group2
2675 BFS order of entries is: EntryA, EntryC, EntryB
2676 BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB
2678 =head1 SYNCHRONIZING
2680 B<TODO> - This is a planned feature, not yet implemented.
2684 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
2685 mechanisms. Fatal errors are propagated using L<functions/die> and non-fatal errors (a.k.a. warnings) are
2686 propagated using L<functions/warn> while adhering to perl's L<warnings> system. If you're already familiar
2687 with these mechanisms, you can skip this section.
2689 You can catch fatal errors using L<functions/eval> (or something like L<Try::Tiny>) and non-fatal errors using
2690 C<$SIG{__WARN__}> (see L<variables/%SIG>). Examples:
2692 use File::KDBX::Error qw(error);
2694 my $key = ''; # uh oh
2696 $kdbx->load_file('whatever.kdbx', $key);
2698 if (my $error = error($@)) {
2699 handle_missing_key($error) if $error->type eq 'key.missing';
2703 or using C<Try::Tiny>:
2706 $kdbx->load_file('whatever.kdbx', $key);
2712 Catching non-fatal errors:
2715 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2717 $kdbx->load_file('whatever.kdbx', $key);
2719 handle_warnings(@warnings) if @warnings;
2721 By default perl prints warnings to C<STDERR> if you don't catch them. If you don't want to catch them and also
2722 don't want them printed to C<STDERR>, you can suppress them lexically (perl v5.28 or higher required):
2725 no warnings 'File::KDBX';
2732 local $File::KDBX::WARNINGS = 0;
2736 or globally in your program:
2738 $File::KDBX::WARNINGS = 0;
2740 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2744 This software will alter its behavior depending on the value of certain environment variables:
2750 C<PERL_FILE_KDBX_XS> - Do not use L<File::KDBX::XS> if false (default: true)
2754 C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
2758 C<NO_FORK> - Do not fork if true (default: false)
2764 Some features (e.g. parsing) require 64-bit perl. It should be possible and actually pretty easy to make it
2765 work using L<Math::BigInt>, but I need to build a 32-bit perl in order to test it and frankly I'm still
2766 figuring out how. I'm sure it's simple so I'll mark this one "TODO", but for now an exception will be thrown
2767 when trying to use such features with undersized IVs.
2775 L<KeePass Password Safe|https://keepass.info/> - The original KeePass
2779 L<KeePassXC|https://keepassxc.org/> - Cross-Platform Password Manager written in C++
2783 L<File::KeePass> has overlapping functionality. It's good but has a backlog of some pretty critical bugs and lacks support for newer KDBX features.
2789 Please report any bugs or feature requests on the bugtracker website
2790 L<https://github.com/chazmcgarvey/File-KDBX/issues>
2792 When submitting a bug or request, please include a test-file or a
2793 patch to an existing test-file that illustrates the bug or desired
2798 Charles McGarvey <ccm@cpan.org>
2800 =head1 COPYRIGHT AND LICENSE
2802 This software is copyright (c) 2022 by Charles McGarvey.
2804 This is free software; you can redistribute it and/or modify it under
2805 the same terms as the Perl 5 programming language system itself.