]> Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX.pm
Release File-KDBX 0.906
[chaz/p5-File-KDBX] / lib / File / KDBX.pm
1 package File::KDBX;
2 # ABSTRACT: Encrypted database to store secret text and files
3
4 use 5.010;
5 use warnings;
6 use strict;
7
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;
13 use File::KDBX::Safe;
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);
19 use Time::Piece 1.33;
20 use boolean;
21 use namespace::clean;
22
23 our $VERSION = '999.999'; # VERSION
24 our $WARNINGS = 1;
25
26 fieldhashes \my (%SAFE, %KEYS);
27
28 =method new
29
30 $kdbx = File::KDBX->new(%attributes);
31 $kdbx = File::KDBX->new($kdbx); # copy constructor
32
33 Construct a new L<File::KDBX>.
34
35 =cut
36
37 sub new {
38 my $class = shift;
39
40 # copy constructor
41 return $_[0]->clone if @_ == 1 && blessed $_[0] && $_[0]->isa($class);
42
43 my $data;
44 $data = shift if is_plain_hashref($_[0]);
45
46 my $self = bless $data // {}, $class;
47 $self->init(@_);
48 $self->_set_nonlazy_attributes if !$data;
49 return $self;
50 }
51
52 sub DESTROY { local ($., $@, $!, $^E, $?); !in_global_destruction and $_[0]->reset }
53
54 =method init
55
56 $kdbx = $kdbx->init(%attributes);
57
58 Initialize a L<File::KDBX> with a set of attributes. Returns itself to allow method chaining.
59
60 This is called by L</new>.
61
62 =cut
63
64 sub init {
65 my $self = shift;
66 my %args = @_;
67
68 @$self{keys %args} = values %args;
69
70 return $self;
71 }
72
73 =method reset
74
75 $kdbx = $kdbx->reset;
76
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
78 method chaining.
79
80 =cut
81
82 sub reset {
83 my $self = shift;
84 erase $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
85 erase $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
86 erase $self->{raw};
87 %$self = ();
88 $self->_remove_safe;
89 return $self;
90 }
91
92 =method clone
93
94 $kdbx_copy = $kdbx->clone;
95 $kdbx_copy = File::KDBX->new($kdbx);
96
97 Clone a L<File::KDBX>. The clone will be an exact copy and completely independent of the original.
98
99 =cut
100
101 sub clone {
102 my $self = shift;
103 require Storable;
104 return Storable::dclone($self);
105 }
106
107 sub STORABLE_freeze {
108 my $self = shift;
109 my $cloning = shift;
110
111 my $copy = {%$self};
112
113 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
114 }
115
116 sub STORABLE_thaw {
117 my $self = shift;
118 my $cloning = shift;
119 shift;
120 my $clone = shift;
121 my $key = shift;
122 my $safe = shift;
123
124 @$self{keys %$clone} = values %$clone;
125 $KEYS{$self} = $key;
126 $SAFE{$self} = $safe;
127
128 # Dualvars aren't cloned as dualvars, so coerce the compression flags.
129 $self->compression_flags($self->compression_flags);
130
131 $self->objects(history => 1)->each(sub { $_->kdbx($self) });
132 }
133
134 ##############################################################################
135
136 =method load
137
138 =method load_string
139
140 =method load_file
141
142 =method load_handle
143
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
148
149 $kdbx = File::KDBX->load_string($string, $key);
150 $kdbx = File::KDBX->load_string(\$string, $key);
151 $kdbx->load_string(...); # also instance method
152
153 $kdbx = File::KDBX->load_file($filepath, $key);
154 $kdbx->load_file(...); # also instance method
155
156 $kdbx = File::KDBX->load_handle($fh, $key);
157 $kdbx = File::KDBX->load_handle(*IO, $key);
158 $kdbx->load_handle(...); # also instance method
159
160 Load a KDBX file from a string buffer, IO handle or file from a filesystem.
161
162 L<File::KDBX::Loader> does the heavy lifting.
163
164 =cut
165
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(@_) }
170
171 sub _loader {
172 my $self = shift;
173 $self = $self->new if !ref $self;
174 require File::KDBX::Loader;
175 File::KDBX::Loader->new(kdbx => $self);
176 }
177
178 =method dump
179
180 =method dump_string
181
182 =method dump_file
183
184 =method dump_handle
185
186 $kdbx->dump(\$string, $key);
187 $kdbx->dump(*IO, $key);
188 $kdbx->dump($filepath, $key);
189
190 $kdbx->dump_string(\$string, $key);
191 \$string = $kdbx->dump_string($key);
192
193 $kdbx->dump_file($filepath, $key);
194
195 $kdbx->dump_handle($fh, $key);
196 $kdbx->dump_handle(*IO, $key);
197
198 Dump a KDBX file to a string buffer, IO handle or file in a filesystem.
199
200 L<File::KDBX::Dumper> does the heavy lifting.
201
202 =cut
203
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(@_) }
208
209 sub _dumper {
210 my $self = shift;
211 $self = $self->new if !ref $self;
212 require File::KDBX::Dumper;
213 File::KDBX::Dumper->new(kdbx => $self);
214 }
215
216 ##############################################################################
217
218 =method user_agent_string
219
220 $string = $kdbx->user_agent_string;
221
222 Get a text string identifying the database client software.
223
224 =cut
225
226 sub user_agent_string {
227 require Config;
228 sprintf('%s/%s (%s/%s; %s/%s; %s)',
229 __PACKAGE__, $VERSION, @Config::Config{qw(package version osname osvers archname)});
230 }
231
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;
235 has headers => {};
236 has inner_headers => {};
237 has meta => {};
238 has binaries => {};
239 has deleted_objects => {};
240 has raw => coerce => \&to_string;
241
242 # HEADERS
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 },
245 coerce => \&to_uuid;
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 {
252 +{
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),
256 };
257 };
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' => {};
263
264 # META
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' => {};
292
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;
299
300 my @ATTRS = (
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,
306 );
307 sub _set_nonlazy_attributes {
308 my $self = shift;
309 $self->$_ for list_attributes(ref $self), @ATTRS;
310 }
311
312 =method memory_protection
313
314 \%settings = $kdbx->memory_protection
315 $kdbx->memory_protection(\%settings);
316
317 $bool = $kdbx->memory_protection($string_key);
318 $kdbx->memory_protection($string_key => $bool);
319
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>
322 strings.
323
324 Memory protection can be toggled individually for each entry string, and individual settings take precedence
325 over these global settings.
326
327 =cut
328
329 sub memory_protection {
330 my $self = shift;
331 $self->{meta}{memory_protection} = shift if @_ == 1 && is_plain_hashref($_[0]);
332 return $self->{meta}{memory_protection} //= {} if !@_;
333
334 my $string_key = shift;
335 my $key = 'protect_' . lc($string_key);
336
337 $self->meta->{memory_protection}{$key} = shift if @_;
338 $self->meta->{memory_protection}{$key};
339 }
340
341 =method minimum_version
342
343 $version = $kdbx->minimum_version;
344
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.
348
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.
351
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.
357
358 =cut
359
360 sub minimum_version {
361 my $self = shift;
362
363 return KDBX_VERSION_4_1 if any {
364 nonempty $_->{last_modification_time}
365 } values %{$self->custom_data};
366
367 return KDBX_VERSION_4_1 if any {
368 nonempty $_->{name} || nonempty $_->{last_modification_time}
369 } @{$self->custom_icons};
370
371 return KDBX_VERSION_4_1 if $self->groups->next(sub {
372 nonempty $_->previous_parent_group ||
373 nonempty $_->tags ||
374 (any { nonempty $_->{last_modification_time} } values %{$_->custom_data})
375 });
376
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})
381 });
382
383 return KDBX_VERSION_4_0 if $self->kdf->uuid ne KDF_UUID_AES;
384
385 return KDBX_VERSION_4_0 if nonempty $self->public_custom_data;
386
387 return KDBX_VERSION_4_0 if $self->objects->next(sub {
388 nonempty $_->custom_data
389 });
390
391 return KDBX_VERSION_3_1;
392 }
393
394 ##############################################################################
395
396 =method root
397
398 $group = $kdbx->root;
399 $kdbx->root($group);
400
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.
403
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
409 database is opened.
410
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.
413
414 =cut
415
416 sub root {
417 my $self = shift;
418 if (@_) {
419 $self->{root} = $self->_wrap_group(@_);
420 $self->{root}->kdbx($self);
421 }
422 $self->{root} //= $self->_implicit_root;
423 return $self->_wrap_group($self->{root});
424 }
425
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.
429 sub _kpx_groups {
430 my $self = shift;
431 return [] if !$self->{root};
432 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
433 }
434
435 sub _has_implicit_root {
436 my $self = shift;
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;
451 }
452
453 sub _implicit_root {
454 my $self = shift;
455 require File::KDBX::Group;
456 return File::KDBX::Group->new(
457 name => 'Root',
458 is_expanded => true,
459 notes => 'Added as an implicit root group by '.__PACKAGE__.'.',
460 ref $self ? (kdbx => $self) : (),
461 );
462 }
463
464 =method trace_lineage
465
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);
470
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.
474
475 =cut
476
477 sub trace_lineage {
478 my $self = shift;
479 my $object = shift;
480 return $object->lineage(@_);
481 }
482
483 sub _trace_lineage {
484 my $self = shift;
485 my $object = shift;
486 my @lineage = @_;
487
488 push @lineage, $self->root if !@lineage;
489 my $base = $lineage[-1] or return [];
490
491 my $uuid = $object->uuid;
492 return \@lineage if any { $_->uuid eq $uuid } @{$base->groups}, @{$base->entries};
493
494 for my $subgroup (@{$base->groups}) {
495 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
496 return $result if $result;
497 }
498 }
499
500 =method recycle_bin
501
502 $group = $kdbx->recycle_bin;
503 $kdbx->recycle_bin($group);
504
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.
507
508 =cut
509
510 sub recycle_bin {
511 my $self = shift;
512 if (my $group = shift) {
513 $self->recycle_bin_uuid($group->uuid);
514 return $group;
515 }
516 my $group;
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,
525 );
526 $self->recycle_bin_uuid($group->uuid);
527 }
528 return $group;
529 }
530
531 =method entry_templates
532
533 $group = $kdbx->entry_templates;
534 $kdbx->entry_templates($group);
535
536 Get or set the entry templates group. May return C<undef> if unset.
537
538 =cut
539
540 sub entry_templates {
541 my $self = shift;
542 if (my $group = shift) {
543 $self->entry_templates_group($group->uuid);
544 return $group;
545 }
546 my $uuid = $self->entry_templates_group;
547 return if $uuid eq UUID_NULL;
548 return $self->groups->grep(uuid => $uuid)->next;
549 }
550
551 =method last_selected
552
553 $group = $kdbx->last_selected;
554 $kdbx->last_selected($group);
555
556 Get or set the last selected group. May return C<undef> if unset.
557
558 =cut
559
560 sub last_selected {
561 my $self = shift;
562 if (my $group = shift) {
563 $self->last_selected_group($group->uuid);
564 return $group;
565 }
566 my $uuid = $self->last_selected_group;
567 return if $uuid eq UUID_NULL;
568 return $self->groups->grep(uuid => $uuid)->next;
569 }
570
571 =method last_top_visible
572
573 $group = $kdbx->last_top_visible;
574 $kdbx->last_top_visible($group);
575
576 Get or set the last top visible group. May return C<undef> if unset.
577
578 =cut
579
580 sub last_top_visible {
581 my $self = shift;
582 if (my $group = shift) {
583 $self->last_top_visible_group($group->uuid);
584 return $group;
585 }
586 my $uuid = $self->last_top_visible_group;
587 return if $uuid eq UUID_NULL;
588 return $self->groups->grep(uuid => $uuid)->next;
589 }
590
591 ##############################################################################
592
593 =method add_group
594
595 $kdbx->add_group($group);
596 $kdbx->add_group(%group_attributes, %options);
597
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:
600
601 =for :list
602 * C<group> - Group object or group UUID to add the group to (default: root group)
603
604 =cut
605
606 sub add_group {
607 my $self = shift;
608 my $group = @_ % 2 == 1 ? shift : undef;
609 my %args = @_;
610
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';
615
616 return $parent->add_group(defined $group ? $group : (), %args, kdbx => $self);
617 }
618
619 sub _wrap_group {
620 my $self = shift;
621 my $group = shift;
622 require File::KDBX::Group;
623 return File::KDBX::Group->wrap($group, $self);
624 }
625
626 =method groups
627
628 \&iterator = $kdbx->groups(%options);
629 \&iterator = $kdbx->groups($base_group, %options);
630
631 Get an L<File::KDBX::Iterator> over I<groups> within a database. Options:
632
633 =for :list
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>)
637
638 =cut
639
640 sub groups {
641 my $self = shift;
642 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
643 my $base = delete $args{base} // $self->root;
644
645 return $base->all_groups(%args);
646 }
647
648 ##############################################################################
649
650 =method add_entry
651
652 $kdbx->add_entry($entry, %options);
653 $kdbx->add_entry(%entry_attributes, %options);
654
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:
657
658 =for :list
659 * C<group> - Group object or group UUID to add the entry to (default: root group)
660
661 =cut
662
663 sub add_entry {
664 my $self = shift;
665 my $entry = @_ % 2 == 1 ? shift : undef;
666 my %args = @_;
667
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';
672
673 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx => $self);
674 }
675
676 sub _wrap_entry {
677 my $self = shift;
678 my $entry = shift;
679 require File::KDBX::Entry;
680 return File::KDBX::Entry->wrap($entry, $self);
681 }
682
683 =method entries
684
685 \&iterator = $kdbx->entries(%options);
686 \&iterator = $kdbx->entries($base_group, %options);
687
688 Get an L<File::KDBX::Iterator> over I<entries> within a database. Supports the same options as L</groups>,
689 plus some new ones:
690
691 =for :list
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)
695
696 =cut
697
698 sub entries {
699 my $self = shift;
700 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
701 my $base = delete $args{base} // $self->root;
702
703 return $base->all_entries(%args);
704 }
705
706 ##############################################################################
707
708 =method objects
709
710 \&iterator = $kdbx->objects(%options);
711 \&iterator = $kdbx->objects($base_group, %options);
712
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>.
716
717 =cut
718
719 sub objects {
720 my $self = shift;
721 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
722 my $base = delete $args{base} // $self->root;
723
724 return $base->all_objects(%args);
725 }
726
727 sub __iter__ { $_[0]->objects }
728
729 ##############################################################################
730
731 =method custom_icon
732
733 \%icon = $kdbx->custom_icon($uuid);
734 $kdbx->custom_icon($uuid => \%icon);
735 $kdbx->custom_icon(%icon);
736 $kdbx->custom_icon(uuid => $value, %icon);
737
738 Get or set custom icons.
739
740 =cut
741
742 sub custom_icon {
743 my $self = shift;
744 my %args = @_ == 2 ? (uuid => shift, data => shift)
745 : @_ % 2 == 1 ? (uuid => shift, @_) : @_;
746
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};
753 }
754 }
755
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 };
759 $i;
760 };
761
762 my $fields = \%args;
763 $fields = $args{data} if is_plain_hashref($args{data});
764
765 while (my ($field, $value) = each %$fields) {
766 $icon->{$field} = $value;
767 }
768 return $icon;
769 }
770
771 =method custom_icon_data
772
773 $image_data = $kdbx->custom_icon_data($uuid);
774
775 Get a custom icon image data.
776
777 =cut
778
779 sub custom_icon_data {
780 my $self = shift;
781 my $uuid = shift // return;
782 my $icon = first { $_->{uuid} eq $uuid } @{$self->custom_icons} or return;
783 return $icon->{data};
784 }
785
786 =method add_custom_icon
787
788 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
789 $uuid = $kdbx->add_custom_icon(%attributes);
790
791 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
792
793 =for :list
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+)
798
799 =cut
800
801 sub add_custom_icon {
802 my $self = shift;
803 my %args = @_ % 2 == 1 ? (data => shift, @_) : @_;
804
805 defined $args{data} or throw 'Must provide image data';
806
807 my $uuid = $args{uuid} // generate_uuid;
808 push @{$self->custom_icons}, {
809 @_,
810 uuid => $uuid,
811 data => $args{data},
812 };
813 return $uuid;
814 }
815
816 =method remove_custom_icon
817
818 $kdbx->remove_custom_icon($uuid);
819
820 Remove a custom icon.
821
822 =cut
823
824 sub remove_custom_icon {
825 my $self = shift;
826 my $uuid = shift;
827 my @deleted;
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;
831 return @deleted;
832 }
833
834 ##############################################################################
835
836 =method custom_data
837
838 \%all_data = $kdbx->custom_data;
839 $kdbx->custom_data(\%all_data);
840
841 \%data = $kdbx->custom_data($key);
842 $kdbx->custom_data($key => \%data);
843 $kdbx->custom_data(%data);
844 $kdbx->custom_data(key => $value, %data);
845
846 Get and set custom data. Custom data is metadata associated with a database.
847
848 Each data item can have a few attributes associated with it.
849
850 =for :list
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+)
854
855 =cut
856
857 sub custom_data {
858 my $self = shift;
859 $self->{meta}{custom_data} = shift if @_ == 1 && is_plain_hashref($_[0]);
860 return $self->{meta}{custom_data} //= {} if !@_;
861
862 my %args = @_ == 2 ? (key => shift, value => shift)
863 : @_ % 2 == 1 ? (key => shift, @_) : @_;
864
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};
871 }
872 }
873
874 my $key = $args{key} or throw 'Must provide a custom_data key to access';
875
876 return $self->{meta}{custom_data}{$key} = $args{value} if is_plain_hashref($args{value});
877
878 while (my ($field, $value) = each %args) {
879 $self->{meta}{custom_data}{$key}{$field} = $value;
880 }
881 return $self->{meta}{custom_data}{$key};
882 }
883
884 =method custom_data_value
885
886 $value = $kdbx->custom_data_value($key);
887
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:
890
891 my $data = $kdbx->custom_data($key);
892 my $value = defined $data ? $data->{value} : undef;
893
894 =cut
895
896 sub custom_data_value {
897 my $self = shift;
898 my $data = $self->custom_data(@_) // return;
899 return $data->{value};
900 }
901
902 =method public_custom_data
903
904 \%all_data = $kdbx->public_custom_data;
905 $kdbx->public_custom_data(\%all_data);
906
907 $value = $kdbx->public_custom_data($key);
908 $kdbx->public_custom_data($key => $value);
909
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:
912
913 =for :list
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)
917
918 =cut
919
920 sub public_custom_data {
921 my $self = shift;
922 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} = shift if @_ == 1 && is_plain_hashref($_[0]);
923 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} //= {} if !@_;
924
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};
928 }
929
930 ##############################################################################
931
932 # TODO
933
934 # sub merge_to {
935 # my $self = shift;
936 # my $other = shift;
937 # my %options = @_; # prefer_old / prefer_new
938 # $other->merge_from($self);
939 # }
940
941 # sub merge_from {
942 # my $self = shift;
943 # my $other = shift;
944
945 # die 'Not implemented';
946 # }
947
948 =method add_deleted_object
949
950 $kdbx->add_deleted_object($uuid);
951
952 Add a UUID to the deleted objects list. This list is used to support automatic database merging.
953
954 You typically do not need to call this yourself because the list will be populated automatically as objects
955 are removed.
956
957 =cut
958
959 sub add_deleted_object {
960 my $self = shift;
961 my $uuid = shift;
962
963 # ignore null and meta stream UUIDs
964 return if $uuid eq UUID_NULL || $uuid eq '0' x 16;
965
966 $self->deleted_objects->{$uuid} = {
967 uuid => $uuid,
968 deletion_time => scalar gmtime,
969 };
970 }
971
972 =method remove_deleted_object
973
974 $kdbx->remove_deleted_object($uuid);
975
976 Remove a UUID from the deleted objects list. This list is used to support automatic database merging.
977
978 You typically do not need to call this yourself because the list will be maintained automatically as objects
979 are added.
980
981 =cut
982
983 sub remove_deleted_object {
984 my $self = shift;
985 my $uuid = shift;
986 delete $self->deleted_objects->{$uuid};
987 }
988
989 =method clear_deleted_objects
990
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.
993
994 =cut
995
996 sub clear_deleted_objects {
997 my $self = shift;
998 %{$self->deleted_objects} = ();
999 }
1000
1001 ##############################################################################
1002
1003 =method resolve_reference
1004
1005 $string = $kdbx->resolve_reference($reference);
1006 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
1007
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.
1012
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.
1016
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:
1019
1020 =for :list
1021 * C<T> - Title
1022 * C<U> - UserName
1023 * C<P> - Password
1024 * C<A> - URL
1025 * C<N> - Notes
1026 * C<I> - UUID
1027 * C<O> - Other custom strings
1028
1029 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
1030
1031 Examples:
1032
1033 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
1034
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"');
1040
1041 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
1042 quotes.
1043
1044 To get the I<Password> string of a specific entry (identified by its UUID):
1045
1046 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
1047
1048 =cut
1049
1050 sub resolve_reference {
1051 my $self = shift;
1052 my $wanted = shift // return;
1053 my $search_in = shift;
1054 my $text = shift;
1055
1056 if (!defined $text) {
1057 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
1058 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
1059 }
1060 $wanted && $search_in && nonempty($text) or return;
1061
1062 my %fields = (
1063 T => 'expand_title',
1064 U => 'expand_username',
1065 P => 'expand_password',
1066 A => 'expand_url',
1067 N => 'expand_notes',
1068 I => 'uuid',
1069 O => 'other_strings',
1070 );
1071 $wanted = $fields{$wanted} or return;
1072 $search_in = $fields{$search_in} or return;
1073
1074 my $query = $search_in eq 'uuid' ? query($search_in => uuid($text))
1075 : simple_expression_query($text, '=~', $search_in);
1076
1077 my $entry = $self->entries->grep($query)->next;
1078 $entry or return;
1079
1080 return $entry->$wanted;
1081 }
1082
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 },
1115 # 'GROUP_SEL'
1116 # 'GROUP_SEL_PATH'
1117 # 'GROUP_SEL_NOTES'
1118 # 'DB_PATH'
1119 # 'DB_DIR'
1120 # 'DB_NAME'
1121 # 'DB_BASENAME'
1122 # 'DB_EXT'
1123 'ENV:' => sub { $ENV{$_[1]} },
1124 'ENV_DIRSEP' => sub { load_optional('File::Spec')->catfile('', '') },
1125 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
1126 # 'T-REPLACE-RX:'
1127 # 'T-CONV:'
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') },
1142 # 'PICKCHARS'
1143 # 'PICKCHARS:'
1144 # 'PICKFIELD'
1145 # 'NEWPASSWORD'
1146 # 'NEWPASSWORD:'
1147 # 'PASSWORD_ENC'
1148 'HMACOTP' => sub { $_[0]->hmac_otp },
1149 'TIMEOTP' => sub { $_[0]->time_otp },
1150 'C:' => sub { '' }, # comment
1151 # 'BASE'
1152 # 'BASE:'
1153 # 'CLIPBOARD'
1154 # 'CLIPBOARD-SET:'
1155 # 'CMD:'
1156 );
1157
1158 ##############################################################################
1159
1160 =method lock
1161
1162 $kdbx->lock;
1163
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.
1167
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.
1170
1171 =cut
1172
1173 sub _safe {
1174 my $self = shift;
1175 $SAFE{$self} = shift if @_;
1176 $SAFE{$self};
1177 }
1178
1179 sub _remove_safe { delete $SAFE{$_[0]} }
1180
1181 sub lock {
1182 my $self = shift;
1183
1184 # Find things to lock:
1185 my @strings;
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);
1191 }
1192 push @strings, grep { $_->{protect} } values %{$_->binaries};
1193 });
1194 return $self if !@strings; # nothing to do
1195
1196 if (my $safe = $self->_safe) {
1197 $safe->add(\@strings);
1198 }
1199 else {
1200 $self->_safe(File::KDBX::Safe->new(\@strings));
1201 }
1202 return $self;
1203 }
1204
1205 =method unlock
1206
1207 $kdbx->unlock;
1208
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.
1211
1212 =cut
1213
1214 sub unlock {
1215 my $self = shift;
1216 my $safe = $self->_safe or return $self;
1217
1218 $safe->unlock;
1219 $self->_remove_safe;
1220
1221 return $self;
1222 }
1223
1224 =method unlock_scoped
1225
1226 $guard = $kdbx->unlock_scoped;
1227
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.
1230
1231 See L</lock> and L</unlock>.
1232
1233 Example:
1234
1235 {
1236 my $guard = $kdbx->unlock_scoped;
1237 ...;
1238 }
1239 # $kdbx is now memory-locked
1240
1241 =cut
1242
1243 sub unlock_scoped {
1244 throw 'Programmer error: Cannot call unlock_scoped in void context' if !defined wantarray;
1245 my $self = shift;
1246 return if !$self->is_locked;
1247 require Scope::Guard;
1248 my $guard = Scope::Guard->new(sub { $self->lock });
1249 $self->unlock;
1250 return $guard;
1251 }
1252
1253 =method peek
1254
1255 $string = $kdbx->peek(\%string);
1256 $string = $kdbx->peek(\%binary);
1257
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>.
1260
1261 =cut
1262
1263 sub peek {
1264 my $self = shift;
1265 my $string = shift;
1266 my $safe = $self->_safe or return;
1267 return $safe->peek($string);
1268 }
1269
1270 =method is_locked
1271
1272 $bool = $kdbx->is_locked;
1273
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.
1277
1278 =cut
1279
1280 sub is_locked { !!$_[0]->_safe }
1281
1282 ##############################################################################
1283
1284 # sub check {
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)
1288 # - Duplicate icons
1289 # - All data types are valid
1290 # - date times are correct
1291 # - boolean fields
1292 # - All UUIDs refer to things that exist
1293 # - previous parent group
1294 # - recycle bin
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?
1302 # }
1303
1304 =method remove_empty_groups
1305
1306 $kdbx->remove_empty_groups;
1307
1308 Remove groups with no subgroups and no entries.
1309
1310 =cut
1311
1312 sub remove_empty_groups {
1313 my $self = shift;
1314 my @removed;
1315 $self->groups(algorithm => 'dfs')
1316 ->where(-true => 'is_empty')
1317 ->each(sub { push @removed, $_->remove });
1318 return @removed;
1319 }
1320
1321 =method remove_unused_icons
1322
1323 $kdbx->remove_unused_icons;
1324
1325 Remove icons that are not associated with any entry or group in the database.
1326
1327 =cut
1328
1329 sub remove_unused_icons {
1330 my $self = shift;
1331 my %icons = map { $_->{uuid} => 0 } @{$self->custom_icons};
1332
1333 $self->objects->each(sub { ++$icons{$_->custom_icon_uuid // ''} });
1334
1335 my @removed;
1336 push @removed, $self->remove_custom_icon($_) for grep { $icons{$_} == 0 } keys %icons;
1337 return @removed;
1338 }
1339
1340 =method remove_duplicate_icons
1341
1342 $kdbx->remove_duplicate_icons;
1343
1344 Remove duplicate icons as determined by hashing the icon data.
1345
1346 =cut
1347
1348 sub remove_duplicate_icons {
1349 my $self = shift;
1350
1351 my %seen;
1352 my %dup;
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};
1357 }
1358 else {
1359 $seen{$digest} = $icon;
1360 }
1361 }
1362
1363 my @removed;
1364 while (my ($old_uuid, $new_uuid) = each %dup) {
1365 $self->objects
1366 ->where(custom_icon_uuid => $old_uuid)
1367 ->each(sub { $_->custom_icon_uuid($new_uuid) });
1368 push @removed, $self->remove_custom_icon($old_uuid);
1369 }
1370 return @removed;
1371 }
1372
1373 =method prune_history
1374
1375 $kdbx->prune_history(%options);
1376
1377 Remove just as many older historical entries as necessary to get under certain limits.
1378
1379 =for :list
1380 * C<max_items> - Maximum number of historical entries to keep (default: value of L</history_max_items>, no
1381 limit: -1)
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)
1386
1387 =cut
1388
1389 sub prune_history {
1390 my $self = shift;
1391 my %args = @_;
1392
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;
1396
1397 my @removed;
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,
1403 );
1404 });
1405 return @removed;
1406 }
1407
1408 =method randomize_seeds
1409
1410 $kdbx->randomize_seeds;
1411
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:
1414
1415 =for :list
1416 * L</encryption_iv>
1417 * L</inner_random_stream_key>
1418 * L</master_seed>
1419 * L</stream_start_bytes>
1420 * L</transform_seed>
1421
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.
1424
1425 =cut
1426
1427 sub randomize_seeds {
1428 my $self = shift;
1429 my $iv_size = 16;
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));
1436 }
1437
1438 ##############################################################################
1439
1440 =method key
1441
1442 $key = $kdbx->key;
1443 $key = $kdbx->key($key);
1444 $key = $kdbx->key($primitive);
1445
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.
1449
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.
1452
1453 =cut
1454
1455 sub key {
1456 my $self = shift;
1457 $KEYS{$self} = File::KDBX::Key->new(@_) if @_;
1458 $KEYS{$self};
1459 }
1460
1461 =method composite_key
1462
1463 $key = $kdbx->composite_key($key);
1464 $key = $kdbx->composite_key($primitive);
1465
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
1468 wrapped.
1469
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.
1472
1473 =cut
1474
1475 sub composite_key {
1476 my $self = shift;
1477 require File::KDBX::Key::Composite;
1478 return File::KDBX::Key::Composite->new(@_);
1479 }
1480
1481 =method kdf
1482
1483 $kdf = $kdbx->kdf(%options);
1484 $kdf = $kdbx->kdf(\%parameters, %options);
1485
1486 Get a L<File::KDBX::KDF> (key derivation function).
1487
1488 Options:
1489
1490 =for :list
1491 * C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
1492
1493 =cut
1494
1495 sub kdf {
1496 my $self = shift;
1497 my %args = @_ % 2 == 1 ? (params => shift, @_) : @_;
1498
1499 my $params = $args{params};
1500
1501 $params //= $self->kdf_parameters;
1502 $params = {%{$params || {}}};
1503
1504 if (empty $params || !defined $params->{+KDF_PARAM_UUID}) {
1505 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES;
1506 }
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;
1514 }
1515 $params->{+KDF_PARAM_AES_SEED} //= $self->transform_seed;
1516 $params->{+KDF_PARAM_AES_ROUNDS} //= $self->transform_rounds;
1517 }
1518
1519 require File::KDBX::KDF;
1520 return File::KDBX::KDF->new(%$params);
1521 }
1522
1523 sub transform_seed {
1524 my $self = shift;
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);
1530 }
1531
1532 sub transform_rounds {
1533 my $self = shift;
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};
1541 }
1542
1543 =method cipher
1544
1545 $cipher = $kdbx->cipher(key => $key);
1546 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
1547
1548 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
1549
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.
1552
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} >>.
1555
1556 You generally don't need to call this directly. The loader and dumper use it to decrypt and encrypt KDBX
1557 files.
1558
1559 =cut
1560
1561 sub cipher {
1562 my $self = shift;
1563 my %args = @_;
1564
1565 $args{uuid} //= $self->cipher_id;
1566 $args{iv} //= $self->encryption_iv;
1567
1568 require File::KDBX::Cipher;
1569 return File::KDBX::Cipher->new(%args);
1570 }
1571
1572 =method random_stream
1573
1574 $cipher = $kdbx->random_stream;
1575 $cipher = $kdbx->random_stream(id => $stream_id, key => $key);
1576
1577 Get a L<File::KDBX::Cipher::Stream> for decrypting and encrypting protected values.
1578
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.
1583
1584 You generally don't need to call this directly. The loader and dumper use it to scramble protected strings.
1585
1586 =cut
1587
1588 sub random_stream {
1589 my $self = shift;
1590 my %args = @_;
1591
1592 $args{stream_id} //= delete $args{id} // $self->inner_random_stream_id;
1593 $args{key} //= $self->inner_random_stream_key;
1594
1595 require File::KDBX::Cipher;
1596 File::KDBX::Cipher->new(%args);
1597 }
1598
1599 sub inner_random_stream_id {
1600 my $self = shift;
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;
1607 };
1608 }
1609
1610 sub inner_random_stream_key {
1611 my $self = shift;
1612 if (@_) {
1613 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1614 # trick anyway.
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;
1619 }
1620 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1621 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} //= random_bytes(64); # 32
1622 }
1623
1624 #########################################################################################
1625
1626 sub _handle_signal {
1627 my $self = shift;
1628 my $object = shift;
1629 my $type = shift;
1630
1631 my %handlers = (
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,
1638 );
1639 my $handler = $handlers{$type} or return;
1640 $self->$handler($object, @_);
1641 }
1642
1643 sub _handle_object_added {
1644 my $self = shift;
1645 my $object = shift;
1646 $self->remove_deleted_object($object->uuid);
1647 }
1648
1649 sub _handle_object_removed {
1650 my $self = shift;
1651 my $object = shift;
1652 my $old_uuid = $object->{uuid} // return;
1653
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} // '');
1659
1660 $self->add_deleted_object($old_uuid);
1661 }
1662
1663 sub _handle_entry_uuid_changed {
1664 my $self = shift;
1665 my $object = shift;
1666 my $new_uuid = shift;
1667 my $old_uuid = shift // return;
1668
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;
1672
1673 $self->entries->each(sub {
1674 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1675
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;
1680 $txn->commit;
1681 }
1682 });
1683 }
1684
1685 sub _handle_group_uuid_changed {
1686 my $self = shift;
1687 my $object = shift;
1688 my $new_uuid = shift;
1689 my $old_uuid = shift // return;
1690
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} // '');
1696
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} // '');
1700 });
1701 $self->entries->each(sub {
1702 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1703 });
1704 }
1705
1706 #########################################################################################
1707
1708 =attr sig1
1709
1710 =attr sig2
1711
1712 =attr version
1713
1714 =attr headers
1715
1716 =attr inner_headers
1717
1718 =attr meta
1719
1720 =attr binaries
1721
1722 =attr deleted_objects
1723
1724 Hash of UUIDs for objects that have been deleted. This includes groups, entries and even custom icons.
1725
1726 =attr raw
1727
1728 Bytes contained within the encrypted layer of a KDBX file. This is only set when using
1729 L<File::KDBX::Loader::Raw>.
1730
1731 =attr comment
1732
1733 A text string associated with the database stored unencrypted in the file header. Often unset.
1734
1735 =attr cipher_id
1736
1737 The UUID of a cipher used to encrypt the database when stored as a file.
1738
1739 See L<File::KDBX::Cipher>.
1740
1741 =attr compression_flags
1742
1743 Configuration for whether or not and how the database gets compressed. See
1744 L<File::KDBX::Constants/":compression">.
1745
1746 =attr master_seed
1747
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
1750 challenge.
1751
1752 The master seed I<should> be changed each time the database is saved to file.
1753
1754 =attr transform_seed
1755
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).
1758
1759 The transform seed I<should> be changed each time the database is saved to file.
1760
1761 =attr transform_rounds
1762
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.
1765
1766 =attr encryption_iv
1767
1768 The initialization vector used by the cipher.
1769
1770 The encryption IV I<should> be changed each time the database is saved to file.
1771
1772 =attr inner_random_stream_key
1773
1774 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1775 within the database.
1776
1777 =attr stream_start_bytes
1778
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
1782 entire file body.
1783
1784 =attr inner_random_stream_id
1785
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">.
1788
1789 =attr kdf_parameters
1790
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>.
1793
1794 =attr generator
1795
1796 The name of the software used to generate the KDBX file.
1797
1798 =attr header_hash
1799
1800 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1801
1802 =attr database_name
1803
1804 Name of the database.
1805
1806 =attr database_name_changed
1807
1808 Timestamp indicating when the database name was last changed.
1809
1810 =attr database_description
1811
1812 Description of the database
1813
1814 =attr database_description_changed
1815
1816 Timestamp indicating when the database description was last changed.
1817
1818 =attr default_username
1819
1820 When a new entry is created, the I<UserName> string will be populated with this value.
1821
1822 =attr default_username_changed
1823
1824 Timestamp indicating when the default username was last changed.
1825
1826 =attr color
1827
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.
1830
1831 =attr master_key_changed
1832
1833 Timestamp indicating when the master key was last changed.
1834
1835 =attr master_key_change_rec
1836
1837 Number of days until the agent should prompt to recommend changing the master key.
1838
1839 =attr master_key_change_force
1840
1841 Number of days until the agent should prompt to force changing the master key.
1842
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.
1845
1846 =attr custom_icons
1847
1848 Array of custom icons that can be associated with groups and entries.
1849
1850 This list can be managed with the methods L</add_custom_icon> and L</remove_custom_icon>.
1851
1852 =attr recycle_bin_enabled
1853
1854 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1855
1856 =attr recycle_bin_uuid
1857
1858 The UUID of a group used to store thrown-away groups and entries.
1859
1860 =attr recycle_bin_changed
1861
1862 Timestamp indicating when the recycle bin group was last changed.
1863
1864 =attr entry_templates_group
1865
1866 The UUID of a group containing template entries used when creating new entries.
1867
1868 =attr entry_templates_group_changed
1869
1870 Timestamp indicating when the entry templates group was last changed.
1871
1872 =attr last_selected_group
1873
1874 The UUID of the previously-selected group.
1875
1876 =attr last_top_visible_group
1877
1878 The UUID of the group visible at the top of the list.
1879
1880 =attr history_max_items
1881
1882 The maximum number of historical entries that should be kept for each entry. Default is 10.
1883
1884 =attr history_max_size
1885
1886 The maximum total size (in bytes) that each individual entry's history is allowed to grow. Default is 6 MiB.
1887
1888 =attr maintenance_history_days
1889
1890 The maximum age (in days) historical entries should be kept. Default it 365.
1891
1892 =attr settings_changed
1893
1894 Timestamp indicating when the database settings were last updated.
1895
1896 =attr protect_title
1897
1898 Alias of the L</memory_protection> setting for the I<Title> string.
1899
1900 =attr protect_username
1901
1902 Alias of the L</memory_protection> setting for the I<UserName> string.
1903
1904 =attr protect_password
1905
1906 Alias of the L</memory_protection> setting for the I<Password> string.
1907
1908 =attr protect_url
1909
1910 Alias of the L</memory_protection> setting for the I<URL> string.
1911
1912 =attr protect_notes
1913
1914 Alias of the L</memory_protection> setting for the I<Notes> string.
1915
1916 =cut
1917
1918 #########################################################################################
1919
1920 sub TO_JSON { +{%{$_[0]}} }
1921
1922 1;
1923 __END__
1924
1925 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
1926
1927 =head1 SYNOPSIS
1928
1929 use File::KDBX;
1930
1931 # Create a new database from scratch
1932 my $kdbx = File::KDBX->new;
1933
1934 # Add some objects to the database
1935 my $group = $kdbx->add_group(
1936 name => 'Passwords',
1937 );
1938 my $entry = $group->add_entry(
1939 title => 'My Bank',
1940 username => 'mreynolds',
1941 password => 's3cr3t',
1942 );
1943
1944 # Save the database to the filesystem
1945 $kdbx->dump_file('passwords.kdbx', 'masterpw changeme');
1946
1947 # Load the database from the filesystem into a new database instance
1948 my $kdbx2 = File::KDBX->load_file('passwords.kdbx', 'masterpw changeme');
1949
1950 # Iterate over database entries, print entry titles
1951 $kdbx2->entries->each(sub($entry, @) {
1952 say 'Entry: ', $entry->title;
1953 });
1954
1955 See L</RECIPES> for more examples.
1956
1957 =head1 DESCRIPTION
1958
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.
1962
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.
1965
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.
1971
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.
1974
1975 =head2 Features
1976
1977 =for :list
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)
1992
1993 =head2 Introduction to KDBX
1994
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.
1999
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.
2002
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.
2010
2011 =head1 RECIPES
2012
2013 =head2 Create a new database
2014
2015 my $kdbx = File::KDBX->new;
2016
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'
2023 );
2024 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
2025
2026 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
2027
2028 =head2 Read an existing database
2029
2030 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
2031 $kdbx->unlock; # cause $entry->password below to be defined
2032
2033 $kdbx->entries->each(sub($entry, @) {
2034 say 'Found password for: ', $entry->title;
2035 say ' Username: ', $entry->username;
2036 say ' Password: ', $entry->password;
2037 });
2038
2039 =head2 Search for entries
2040
2041 my @entries = $kdbx->entries(searching => 1)
2042 ->grep(title => 'WayneCorp')
2043 ->each; # return all matches
2044
2045 The C<searching> option limits results to only entries within groups with searching enabled. Other options are
2046 also available. See L</entries>.
2047
2048 See L</QUERY> for many more query examples.
2049
2050 =head2 Search for entries by auto-type window association
2051
2052 my $window_title = 'WayneCorp - Mozilla Firefox';
2053
2054 my $entries = $kdbx->entries(auto_type => 1)
2055 ->filter(sub {
2056 my ($ata) = grep { $_->{window} =~ /\Q$window_title\E/i } @{$_->auto_type_associations};
2057 return [$_, $ata->{keystroke_sequence}] if $ata;
2058 })
2059 ->each(sub {
2060 my ($entry, $keys) = @$_;
2061 say 'Entry title: ', $entry->title, ', key sequence: ', $keys;
2062 });
2063
2064 Example output:
2065
2066 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
2067
2068 =head2 Remove entries from a database
2069
2070 $kdbx->entries
2071 ->grep(notes => {'=~' => qr/too old/i})
2072 ->each(sub { $_->recycle });
2073
2074 Recycle all entries with the string "too old" appearing in the B<Notes> string.
2075
2076 =head2 Remove empty groups
2077
2078 $kdbx->groups(algorithm => 'dfs')
2079 ->where(-true => 'is_empty')
2080 ->each('remove');
2081
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.
2084
2085 This can also be done with one call to L</remove_empty_groups>.
2086
2087 =head1 SECURITY
2088
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:
2091
2092 =for :list
2093 * Using unguessable passwords, passphrases and key files.
2094 * Using a brute-force resistent key derivation function.
2095
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.
2098
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.
2102
2103 How expensive you want to make each attempt is up to you and can depend on the application.
2104
2105 This and other KDBX-related security issues are covered here more in depth:
2106 L<https://keepass.info/help/base/security.html>
2107
2108 Here are other security risks you should be thinking about:
2109
2110 =head2 Cryptography
2111
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.
2115
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
2118 generation:
2119
2120 =for :list
2121 * AES-128 (legacy)
2122 * AES-256
2123 * Argon2d & Argon2id
2124 * CBC block mode
2125 * HMAC-SHA256
2126 * SHA256
2127 * SHA512
2128 * Salsa20 & ChaCha20
2129 * Twofish
2130
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.
2133
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.
2137
2138 =head2 Memory Protection
2139
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.
2144
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.
2147
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.
2150
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.
2154
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.
2162
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.
2169
2170 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
2171
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.
2175
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.
2179
2180 =head1 QUERY
2181
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>.
2184
2185 my $filtered_entries = $kdbx->entries->where(\&query);
2186
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
2189 that first.
2190
2191 =head2 Simple Expression
2192
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>.
2195
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.
2199
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>.
2203
2204 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
2205
2206 my $entries = $kdbx->entries->where(\'canyon', qw[title]);
2207
2208 Notice the first argument is a B<scalarref>. This disambiguates a simple expression from other types of
2209 queries covered below.
2210
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:
2213
2214 my $entries = $kdbx->entries->where(\'red canyon', qw[title]);
2215
2216 Each term in the simple expression must be found for an entry to match.
2217
2218 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
2219
2220 my $entries = $kdbx->entries->where(\'red -canyon', qw[title]);
2221
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:
2224
2225 my $entries = $kdbx->entries->where(\'grocery -Foodland', qw[title notes]);
2226
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:
2230
2231 my $entries = $kdbx->entries->where(\5, '>=', qw[usage_count]);
2232
2233 It helps to read it right-to-left, like "usage_count is greater than or equal to 5".
2234
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:
2238
2239 my $entries = $kdbx->entries->where(simple_expression_query(5, '>=', qw[usage_count]));
2240
2241 =head2 Declarative Syntax
2242
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.
2245
2246 To search for all entries in a database titled "My Bank":
2247
2248 my $entries = $kdbx->entries->where({ title => 'My Bank' });
2249
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
2254 a match.
2255
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
2258 B<AND> username:
2259
2260 my $entries = $kdbx->entries->where({
2261 url => 'https://example.com',
2262 username => 'neo',
2263 });
2264
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:
2267
2268 my $entries = $kdbx->entries->where([ # <-- Notice the square bracket
2269 url => 'https://example.com',
2270 username => 'neo',
2271 ]);
2272
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
2275 icon:
2276
2277 my $entries = $kdbx->entries->where({
2278 icon_id => { '==', ICON_SMARTPHONE },
2279 });
2280
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.
2283
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
2286 operators are:
2287
2288 =for :list
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
2305
2306 Other special operators:
2307
2308 =for :list
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
2318
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:
2321
2322 my $groups = $kdbx->groups->where(
2323 uuid => {
2324 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
2325 },
2326 );
2327
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.
2331
2332 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2333
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).
2336
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:
2339
2340 my $entries = $kdbx->entries->where('!' => 'quality_check');
2341
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):
2345
2346 my $entries = $kdbx->entries->where('!!' => 'quality_check');
2347 my $entries = $kdbx->entries->where(-true => 'quality_check'); # same thing
2348
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:
2352
2353 my $entries = $kdbx->entries->where(-not => { title => 'My Bank' });
2354 my $entries = $kdbx->entries->where(title => { 'ne' => 'My Bank' });
2355
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:
2358
2359 my $entries = $kdbx->entries->where({
2360 title => { '=~', qr/bank/ },
2361 -not => {
2362 -or => {
2363 notes => { '=~', qr/business/ },
2364 icon_id => { '==', ICON_TRASHCAN_FULL },
2365 },
2366 },
2367 });
2368
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.
2371
2372 =head2 Subroutine Query
2373
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>.
2378
2379 To review the different types of queries, these are all equivalent to find all entries in the database titled
2380 "My Bank":
2381
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
2385
2386 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2387
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:
2391
2392 my $entries = $kdbx->entries;
2393 while (my $entry = $entries->next) {
2394 if (wanted($entry)) {
2395 do_something($entry);
2396 }
2397 else {
2398 ...
2399 }
2400 }
2401
2402 =head2 Iteration
2403
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">:
2407
2408 =for :list
2409 * C<ITERATION_IDS> - Iterative deepening search (default)
2410 * C<ITERATION_DFS> - Depth-first search
2411 * C<ITERATION_BFS> - Breadth-first search
2412
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.
2415
2416 If you have a database tree like this:
2417
2418 Database
2419 - Root
2420 - Group1
2421 - EntryA
2422 - Group2
2423 - EntryB
2424 - Group3
2425 - EntryC
2426
2427 =for :list
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
2437
2438 =head1 SYNCHRONIZING
2439
2440 B<TODO> - This is a planned feature, not yet implemented.
2441
2442 =head1 ERRORS
2443
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.
2448
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:
2451
2452 use File::KDBX::Error qw(error);
2453
2454 my $key = ''; # uh oh
2455 eval {
2456 $kdbx->load_file('whatever.kdbx', $key);
2457 };
2458 if (my $error = error($@)) {
2459 handle_missing_key($error) if $error->type eq 'key.missing';
2460 $error->throw;
2461 }
2462
2463 or using C<Try::Tiny>:
2464
2465 try {
2466 $kdbx->load_file('whatever.kdbx', $key);
2467 }
2468 catch {
2469 handle_error($_);
2470 };
2471
2472 Catching non-fatal errors:
2473
2474 my @warnings;
2475 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2476
2477 $kdbx->load_file('whatever.kdbx', $key);
2478
2479 handle_warnings(@warnings) if @warnings;
2480
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):
2483
2484 {
2485 no warnings 'File::KDBX';
2486 ...
2487 }
2488
2489 or locally:
2490
2491 {
2492 local $File::KDBX::WARNINGS = 0;
2493 ...
2494 }
2495
2496 or globally in your program:
2497
2498 $File::KDBX::WARNINGS = 0;
2499
2500 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2501
2502 =head1 ENVIRONMENT
2503
2504 This software will alter its behavior depending on the value of certain environment variables:
2505
2506 =for :list
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)
2510
2511 =head1 SEE ALSO
2512
2513 =for :list
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.
2518
2519 =begin :header
2520
2521 =begin markdown
2522
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)
2526
2527 =end markdown
2528
2529 =begin HTML
2530
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>
2534
2535 =end HTML
2536
2537 =end :header
2538
2539 =cut
This page took 0.224049 seconds and 5 git commands to generate.