]> Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX.pm
Version 0.903
[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 = '0.903'; # VERSION
24 our $WARNINGS = 1;
25
26 fieldhashes \my (%SAFE, %KEYS);
27
28
29 sub new {
30 my $class = shift;
31
32 # copy constructor
33 return $_[0]->clone if @_ == 1 && blessed $_[0] && $_[0]->isa($class);
34
35 my $self = bless {}, $class;
36 $self->init(@_);
37 $self->_set_nonlazy_attributes if empty $self;
38 return $self;
39 }
40
41 sub DESTROY { local ($., $@, $!, $^E, $?); !in_global_destruction and $_[0]->reset }
42
43
44 sub init {
45 my $self = shift;
46 my %args = @_;
47
48 @$self{keys %args} = values %args;
49
50 return $self;
51 }
52
53
54 sub reset {
55 my $self = shift;
56 erase $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
57 erase $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
58 erase $self->{raw};
59 %$self = ();
60 $self->_remove_safe;
61 return $self;
62 }
63
64
65 sub clone {
66 my $self = shift;
67 require Storable;
68 return Storable::dclone($self);
69 }
70
71 sub STORABLE_freeze {
72 my $self = shift;
73 my $cloning = shift;
74
75 my $copy = {%$self};
76
77 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
78 }
79
80 sub STORABLE_thaw {
81 my $self = shift;
82 my $cloning = shift;
83 shift;
84 my $clone = shift;
85 my $key = shift;
86 my $safe = shift;
87
88 @$self{keys %$clone} = values %$clone;
89 $KEYS{$self} = $key;
90 $SAFE{$self} = $safe;
91
92 # Dualvars aren't cloned as dualvars, so coerce the compression flags.
93 $self->compression_flags($self->compression_flags);
94
95 $self->objects(history => 1)->each(sub { $_->kdbx($self) });
96 }
97
98 ##############################################################################
99
100
101 sub load { shift->_loader->load(@_) }
102 sub load_string { shift->_loader->load_string(@_) }
103 sub load_file { shift->_loader->load_file(@_) }
104 sub load_handle { shift->_loader->load_handle(@_) }
105
106 sub _loader {
107 my $self = shift;
108 $self = $self->new if !ref $self;
109 require File::KDBX::Loader;
110 File::KDBX::Loader->new(kdbx => $self);
111 }
112
113
114 sub dump { shift->_dumper->dump(@_) }
115 sub dump_string { shift->_dumper->dump_string(@_) }
116 sub dump_file { shift->_dumper->dump_file(@_) }
117 sub dump_handle { shift->_dumper->dump_handle(@_) }
118
119 sub _dumper {
120 my $self = shift;
121 $self = $self->new if !ref $self;
122 require File::KDBX::Dumper;
123 File::KDBX::Dumper->new(kdbx => $self);
124 }
125
126 ##############################################################################
127
128
129 sub user_agent_string {
130 require Config;
131 sprintf('%s/%s (%s/%s; %s/%s; %s)',
132 __PACKAGE__, $VERSION, @Config::Config{qw(package version osname osvers archname)});
133 }
134
135 has sig1 => KDBX_SIG1, coerce => \&to_number;
136 has sig2 => KDBX_SIG2_2, coerce => \&to_number;
137 has version => KDBX_VERSION_3_1, coerce => \&to_number;
138 has headers => {};
139 has inner_headers => {};
140 has meta => {};
141 has binaries => {};
142 has deleted_objects => {};
143 has raw => coerce => \&to_string;
144
145 # HEADERS
146 has 'headers.comment' => '', coerce => \&to_string;
147 has 'headers.cipher_id' => CIPHER_UUID_CHACHA20, coerce => \&to_uuid;
148 has 'headers.compression_flags' => COMPRESSION_GZIP, coerce => \&to_compression_constant;
149 has 'headers.master_seed' => sub { random_bytes(32) }, coerce => \&to_string;
150 has 'headers.encryption_iv' => sub { random_bytes(16) }, coerce => \&to_string;
151 has 'headers.stream_start_bytes' => sub { random_bytes(32) }, coerce => \&to_string;
152 has 'headers.kdf_parameters' => sub {
153 +{
154 KDF_PARAM_UUID() => KDF_UUID_AES,
155 KDF_PARAM_AES_ROUNDS() => $_[0]->headers->{+HEADER_TRANSFORM_ROUNDS} // KDF_DEFAULT_AES_ROUNDS,
156 KDF_PARAM_AES_SEED() => $_[0]->headers->{+HEADER_TRANSFORM_SEED} // random_bytes(32),
157 };
158 };
159 # has 'headers.transform_seed' => sub { random_bytes(32) };
160 # has 'headers.transform_rounds' => 100_000;
161 # has 'headers.inner_random_stream_key' => sub { random_bytes(32) }; # 64 ?
162 # has 'headers.inner_random_stream_id' => STREAM_ID_CHACHA20;
163 # has 'headers.public_custom_data' => {};
164
165 # META
166 has 'meta.generator' => '', coerce => \&to_string;
167 has 'meta.header_hash' => '', coerce => \&to_string;
168 has 'meta.database_name' => '', coerce => \&to_string;
169 has 'meta.database_name_changed' => sub { gmtime }, coerce => \&to_time;
170 has 'meta.database_description' => '', coerce => \&to_string;
171 has 'meta.database_description_changed' => sub { gmtime }, coerce => \&to_time;
172 has 'meta.default_username' => '', coerce => \&to_string;
173 has 'meta.default_username_changed' => sub { gmtime }, coerce => \&to_time;
174 has 'meta.maintenance_history_days' => HISTORY_DEFAULT_MAX_AGE, coerce => \&to_number;
175 has 'meta.color' => '', coerce => \&to_string;
176 has 'meta.master_key_changed' => sub { gmtime }, coerce => \&to_time;
177 has 'meta.master_key_change_rec' => -1, coerce => \&to_number;
178 has 'meta.master_key_change_force' => -1, coerce => \&to_number;
179 # has 'meta.memory_protection' => {};
180 has 'meta.custom_icons' => [];
181 has 'meta.recycle_bin_enabled' => true, coerce => \&to_bool;
182 has 'meta.recycle_bin_uuid' => UUID_NULL, coerce => \&to_uuid;
183 has 'meta.recycle_bin_changed' => sub { gmtime }, coerce => \&to_time;
184 has 'meta.entry_templates_group' => UUID_NULL, coerce => \&to_uuid;
185 has 'meta.entry_templates_group_changed' => sub { gmtime }, coerce => \&to_time;
186 has 'meta.last_selected_group' => UUID_NULL, coerce => \&to_uuid;
187 has 'meta.last_top_visible_group' => UUID_NULL, coerce => \&to_uuid;
188 has 'meta.history_max_items' => HISTORY_DEFAULT_MAX_ITEMS, coerce => \&to_number;
189 has 'meta.history_max_size' => HISTORY_DEFAULT_MAX_SIZE, coerce => \&to_number;
190 has 'meta.settings_changed' => sub { gmtime }, coerce => \&to_time;
191 # has 'meta.binaries' => {};
192 # has 'meta.custom_data' => {};
193
194 has 'memory_protection.protect_title' => false, coerce => \&to_bool;
195 has 'memory_protection.protect_username' => false, coerce => \&to_bool;
196 has 'memory_protection.protect_password' => true, coerce => \&to_bool;
197 has 'memory_protection.protect_url' => false, coerce => \&to_bool;
198 has 'memory_protection.protect_notes' => false, coerce => \&to_bool;
199 # has 'memory_protection.auto_enable_visual_hiding' => false;
200
201 my @ATTRS = (
202 HEADER_TRANSFORM_SEED,
203 HEADER_TRANSFORM_ROUNDS,
204 HEADER_INNER_RANDOM_STREAM_KEY,
205 HEADER_INNER_RANDOM_STREAM_ID,
206 HEADER_PUBLIC_CUSTOM_DATA,
207 );
208 sub _set_nonlazy_attributes {
209 my $self = shift;
210 $self->$_ for list_attributes(ref $self), @ATTRS;
211 }
212
213
214 sub memory_protection {
215 my $self = shift;
216 $self->{meta}{memory_protection} = shift if @_ == 1 && is_plain_hashref($_[0]);
217 return $self->{meta}{memory_protection} //= {} if !@_;
218
219 my $string_key = shift;
220 my $key = 'protect_' . lc($string_key);
221
222 $self->meta->{memory_protection}{$key} = shift if @_;
223 $self->meta->{memory_protection}{$key};
224 }
225
226
227 sub minimum_version {
228 my $self = shift;
229
230 return KDBX_VERSION_4_1 if any {
231 nonempty $_->{last_modification_time}
232 } values %{$self->custom_data};
233
234 return KDBX_VERSION_4_1 if any {
235 nonempty $_->{name} || nonempty $_->{last_modification_time}
236 } @{$self->custom_icons};
237
238 return KDBX_VERSION_4_1 if $self->groups->next(sub {
239 nonempty $_->previous_parent_group ||
240 nonempty $_->tags ||
241 (any { nonempty $_->{last_modification_time} } values %{$_->custom_data})
242 });
243
244 return KDBX_VERSION_4_1 if $self->entries(history => 1)->next(sub {
245 nonempty $_->previous_parent_group ||
246 (defined $_->quality_check && !$_->quality_check) ||
247 (any { nonempty $_->{last_modification_time} } values %{$_->custom_data})
248 });
249
250 return KDBX_VERSION_4_0 if $self->kdf->uuid ne KDF_UUID_AES;
251
252 return KDBX_VERSION_4_0 if nonempty $self->public_custom_data;
253
254 return KDBX_VERSION_4_0 if $self->objects->next(sub {
255 nonempty $_->custom_data
256 });
257
258 return KDBX_VERSION_3_1;
259 }
260
261 ##############################################################################
262
263
264 sub root {
265 my $self = shift;
266 if (@_) {
267 $self->{root} = $self->_wrap_group(@_);
268 $self->{root}->kdbx($self);
269 }
270 $self->{root} //= $self->_implicit_root;
271 return $self->_wrap_group($self->{root});
272 }
273
274 # Called by File::KeePass::KDBX so that a File::KDBX an be treated as a File::KDBX::Group in that both types
275 # can have subgroups. File::KDBX already has a `groups' method that does something different from the
276 # File::KDBX::Groups `groups' method.
277 sub _kpx_groups {
278 my $self = shift;
279 return [] if !$self->{root};
280 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
281 }
282
283 sub _has_implicit_root {
284 my $self = shift;
285 my $root = $self->root;
286 my $temp = __PACKAGE__->_implicit_root;
287 # If an implicit root group has been changed in any significant way, it is no longer implicit.
288 return $root->name eq $temp->name &&
289 $root->is_expanded ^ $temp->is_expanded &&
290 $root->notes eq $temp->notes &&
291 !@{$root->entries} &&
292 !defined $root->custom_icon_uuid &&
293 !keys %{$root->custom_data} &&
294 $root->icon_id == $temp->icon_id &&
295 $root->expires ^ $temp->expires &&
296 $root->default_auto_type_sequence eq $temp->default_auto_type_sequence &&
297 !defined $root->enable_auto_type &&
298 !defined $root->enable_searching;
299 }
300
301 sub _implicit_root {
302 my $self = shift;
303 require File::KDBX::Group;
304 return File::KDBX::Group->new(
305 name => 'Root',
306 is_expanded => true,
307 notes => 'Added as an implicit root group by '.__PACKAGE__.'.',
308 ref $self ? (kdbx => $self) : (),
309 );
310 }
311
312
313 sub trace_lineage {
314 my $self = shift;
315 my $object = shift;
316 return $object->lineage(@_);
317 }
318
319 sub _trace_lineage {
320 my $self = shift;
321 my $object = shift;
322 my @lineage = @_;
323
324 push @lineage, $self->root if !@lineage;
325 my $base = $lineage[-1] or return [];
326
327 my $uuid = $object->uuid;
328 return \@lineage if any { $_->uuid eq $uuid } @{$base->groups}, @{$base->entries};
329
330 for my $subgroup (@{$base->groups}) {
331 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
332 return $result if $result;
333 }
334 }
335
336
337 sub recycle_bin {
338 my $self = shift;
339 if (my $group = shift) {
340 $self->recycle_bin_uuid($group->uuid);
341 return $group;
342 }
343 my $group;
344 my $uuid = $self->recycle_bin_uuid;
345 $group = $self->groups->grep(uuid => $uuid)->next if $uuid ne UUID_NULL;
346 if (!$group && $self->recycle_bin_enabled) {
347 $group = $self->add_group(
348 name => 'Recycle Bin',
349 icon_id => ICON_TRASHCAN_FULL,
350 enable_auto_type => false,
351 enable_searching => false,
352 );
353 $self->recycle_bin_uuid($group->uuid);
354 }
355 return $group;
356 }
357
358
359 sub entry_templates {
360 my $self = shift;
361 if (my $group = shift) {
362 $self->entry_templates_group($group->uuid);
363 return $group;
364 }
365 my $uuid = $self->entry_templates_group;
366 return if $uuid eq UUID_NULL;
367 return $self->groups->grep(uuid => $uuid)->next;
368 }
369
370
371 sub last_selected {
372 my $self = shift;
373 if (my $group = shift) {
374 $self->last_selected_group($group->uuid);
375 return $group;
376 }
377 my $uuid = $self->last_selected_group;
378 return if $uuid eq UUID_NULL;
379 return $self->groups->grep(uuid => $uuid)->next;
380 }
381
382
383 sub last_top_visible {
384 my $self = shift;
385 if (my $group = shift) {
386 $self->last_top_visible_group($group->uuid);
387 return $group;
388 }
389 my $uuid = $self->last_top_visible_group;
390 return if $uuid eq UUID_NULL;
391 return $self->groups->grep(uuid => $uuid)->next;
392 }
393
394 ##############################################################################
395
396
397 sub add_group {
398 my $self = shift;
399 my $group = @_ % 2 == 1 ? shift : undef;
400 my %args = @_;
401
402 # find the right group to add the group to
403 my $parent = delete $args{group} // $self->root;
404 $parent = $self->groups->grep({uuid => $parent})->next if !ref $parent;
405 $parent or throw 'Invalid group';
406
407 return $parent->add_group(defined $group ? $group : (), %args, kdbx => $self);
408 }
409
410 sub _wrap_group {
411 my $self = shift;
412 my $group = shift;
413 require File::KDBX::Group;
414 return File::KDBX::Group->wrap($group, $self);
415 }
416
417
418 sub groups {
419 my $self = shift;
420 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
421 my $base = delete $args{base} // $self->root;
422
423 return $base->all_groups(%args);
424 }
425
426 ##############################################################################
427
428
429 sub add_entry {
430 my $self = shift;
431 my $entry = @_ % 2 == 1 ? shift : undef;
432 my %args = @_;
433
434 # find the right group to add the entry to
435 my $parent = delete $args{group} // $self->root;
436 $parent = $self->groups->grep({uuid => $parent})->next if !ref $parent;
437 $parent or throw 'Invalid group';
438
439 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx => $self);
440 }
441
442 sub _wrap_entry {
443 my $self = shift;
444 my $entry = shift;
445 require File::KDBX::Entry;
446 return File::KDBX::Entry->wrap($entry, $self);
447 }
448
449
450 sub entries {
451 my $self = shift;
452 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
453 my $base = delete $args{base} // $self->root;
454
455 return $base->all_entries(%args);
456 }
457
458 ##############################################################################
459
460
461 sub objects {
462 my $self = shift;
463 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
464 my $base = delete $args{base} // $self->root;
465
466 return $base->all_objects(%args);
467 }
468
469 sub __iter__ { $_[0]->objects }
470
471 ##############################################################################
472
473
474 sub custom_icon {
475 my $self = shift;
476 my %args = @_ == 2 ? (uuid => shift, data => shift)
477 : @_ % 2 == 1 ? (uuid => shift, @_) : @_;
478
479 if (!$args{uuid} && !$args{data}) {
480 my %standard = (uuid => 1, data => 1, name => 1, last_modification_time => 1);
481 my @other_keys = grep { !$standard{$_} } keys %args;
482 if (@other_keys == 1) {
483 my $key = $args{key} = $other_keys[0];
484 $args{data} = delete $args{$key};
485 }
486 }
487
488 my $uuid = $args{uuid} or throw 'Must provide a custom icon UUID to access';
489 my $icon = (first { $_->{uuid} eq $uuid } @{$self->custom_icons}) // do {
490 push @{$self->custom_icons}, my $i = { uuid => $uuid };
491 $i;
492 };
493
494 my $fields = \%args;
495 $fields = $args{data} if is_plain_hashref($args{data});
496
497 while (my ($field, $value) = each %$fields) {
498 $icon->{$field} = $value;
499 }
500 return $icon;
501 }
502
503
504 sub custom_icon_data {
505 my $self = shift;
506 my $uuid = shift // return;
507 my $icon = first { $_->{uuid} eq $uuid } @{$self->custom_icons} or return;
508 return $icon->{data};
509 }
510
511
512 sub add_custom_icon {
513 my $self = shift;
514 my %args = @_ % 2 == 1 ? (data => shift, @_) : @_;
515
516 defined $args{data} or throw 'Must provide image data';
517
518 my $uuid = $args{uuid} // generate_uuid;
519 push @{$self->custom_icons}, {
520 @_,
521 uuid => $uuid,
522 data => $args{data},
523 };
524 return $uuid;
525 }
526
527
528 sub remove_custom_icon {
529 my $self = shift;
530 my $uuid = shift;
531 my @deleted;
532 @{$self->custom_icons} = grep { $_->{uuid} eq $uuid ? do { push @deleted, $_; 0 } : 1 }
533 @{$self->custom_icons};
534 $self->add_deleted_object($uuid) if @deleted;
535 return @deleted;
536 }
537
538 ##############################################################################
539
540
541 sub custom_data {
542 my $self = shift;
543 $self->{meta}{custom_data} = shift if @_ == 1 && is_plain_hashref($_[0]);
544 return $self->{meta}{custom_data} //= {} if !@_;
545
546 my %args = @_ == 2 ? (key => shift, value => shift)
547 : @_ % 2 == 1 ? (key => shift, @_) : @_;
548
549 if (!$args{key} && !$args{value}) {
550 my %standard = (key => 1, value => 1, last_modification_time => 1);
551 my @other_keys = grep { !$standard{$_} } keys %args;
552 if (@other_keys == 1) {
553 my $key = $args{key} = $other_keys[0];
554 $args{value} = delete $args{$key};
555 }
556 }
557
558 my $key = $args{key} or throw 'Must provide a custom_data key to access';
559
560 return $self->{meta}{custom_data}{$key} = $args{value} if is_plain_hashref($args{value});
561
562 while (my ($field, $value) = each %args) {
563 $self->{meta}{custom_data}{$key}{$field} = $value;
564 }
565 return $self->{meta}{custom_data}{$key};
566 }
567
568
569 sub custom_data_value {
570 my $self = shift;
571 my $data = $self->custom_data(@_) // return;
572 return $data->{value};
573 }
574
575
576 sub public_custom_data {
577 my $self = shift;
578 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} = shift if @_ == 1 && is_plain_hashref($_[0]);
579 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} //= {} if !@_;
580
581 my $key = shift or throw 'Must provide a public_custom_data key to access';
582 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key} = shift if @_;
583 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key};
584 }
585
586 ##############################################################################
587
588 # TODO
589
590 # sub merge_to {
591 # my $self = shift;
592 # my $other = shift;
593 # my %options = @_; # prefer_old / prefer_new
594 # $other->merge_from($self);
595 # }
596
597 # sub merge_from {
598 # my $self = shift;
599 # my $other = shift;
600
601 # die 'Not implemented';
602 # }
603
604
605 sub add_deleted_object {
606 my $self = shift;
607 my $uuid = shift;
608
609 # ignore null and meta stream UUIDs
610 return if $uuid eq UUID_NULL || $uuid eq '0' x 16;
611
612 $self->deleted_objects->{$uuid} = {
613 uuid => $uuid,
614 deletion_time => scalar gmtime,
615 };
616 }
617
618
619 sub remove_deleted_object {
620 my $self = shift;
621 my $uuid = shift;
622 delete $self->deleted_objects->{$uuid};
623 }
624
625
626 sub clear_deleted_objects {
627 my $self = shift;
628 %{$self->deleted_objects} = ();
629 }
630
631 ##############################################################################
632
633
634 sub resolve_reference {
635 my $self = shift;
636 my $wanted = shift // return;
637 my $search_in = shift;
638 my $text = shift;
639
640 if (!defined $text) {
641 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
642 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
643 }
644 $wanted && $search_in && nonempty($text) or return;
645
646 my %fields = (
647 T => 'expand_title',
648 U => 'expand_username',
649 P => 'expand_password',
650 A => 'expand_url',
651 N => 'expand_notes',
652 I => 'uuid',
653 O => 'other_strings',
654 );
655 $wanted = $fields{$wanted} or return;
656 $search_in = $fields{$search_in} or return;
657
658 my $query = $search_in eq 'uuid' ? query($search_in => uuid($text))
659 : simple_expression_query($text, '=~', $search_in);
660
661 my $entry = $self->entries->grep($query)->next;
662 $entry or return;
663
664 return $entry->$wanted;
665 }
666
667 our %PLACEHOLDERS = (
668 # 'PLACEHOLDER' => sub { my ($entry, $arg) = @_; ... };
669 'TITLE' => sub { $_[0]->expand_title },
670 'USERNAME' => sub { $_[0]->expand_username },
671 'PASSWORD' => sub { $_[0]->expand_password },
672 'NOTES' => sub { $_[0]->expand_notes },
673 'S:' => sub { $_[0]->string_value($_[1]) },
674 'URL' => sub { $_[0]->expand_url },
675 'URL:RMVSCM' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
676 'URL:WITHOUTSCHEME' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
677 'URL:SCM' => sub { (split_url($_[0]->url))[0] },
678 'URL:SCHEME' => sub { (split_url($_[0]->url))[0] }, # non-standard
679 'URL:HOST' => sub { (split_url($_[0]->url))[2] },
680 'URL:PORT' => sub { (split_url($_[0]->url))[3] },
681 'URL:PATH' => sub { (split_url($_[0]->url))[4] },
682 'URL:QUERY' => sub { (split_url($_[0]->url))[5] },
683 'URL:HASH' => sub { (split_url($_[0]->url))[6] }, # non-standard
684 'URL:FRAGMENT' => sub { (split_url($_[0]->url))[6] }, # non-standard
685 'URL:USERINFO' => sub { (split_url($_[0]->url))[1] },
686 'URL:USERNAME' => sub { (split_url($_[0]->url))[7] },
687 'URL:PASSWORD' => sub { (split_url($_[0]->url))[8] },
688 'UUID' => sub { local $_ = format_uuid($_[0]->uuid); s/-//g; $_ },
689 'REF:' => sub { $_[0]->kdbx->resolve_reference($_[1]) },
690 'INTERNETEXPLORER' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('iexplore') },
691 'FIREFOX' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('firefox') },
692 'GOOGLECHROME' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('google-chrome') },
693 'OPERA' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('opera') },
694 'SAFARI' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('safari') },
695 'APPDIR' => sub { load_optional('FindBin'); $FindBin::Bin },
696 'GROUP' => sub { my $p = $_[0]->group; $p ? $p->name : undef },
697 'GROUP_PATH' => sub { $_[0]->path },
698 'GROUP_NOTES' => sub { my $p = $_[0]->group; $p ? $p->notes : undef },
699 # 'GROUP_SEL'
700 # 'GROUP_SEL_PATH'
701 # 'GROUP_SEL_NOTES'
702 # 'DB_PATH'
703 # 'DB_DIR'
704 # 'DB_NAME'
705 # 'DB_BASENAME'
706 # 'DB_EXT'
707 'ENV:' => sub { $ENV{$_[1]} },
708 'ENV_DIRSEP' => sub { load_optional('File::Spec')->catfile('', '') },
709 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
710 # 'T-REPLACE-RX:'
711 # 'T-CONV:'
712 'DT_SIMPLE' => sub { localtime->strftime('%Y%m%d%H%M%S') },
713 'DT_YEAR' => sub { localtime->strftime('%Y') },
714 'DT_MONTH' => sub { localtime->strftime('%m') },
715 'DT_DAY' => sub { localtime->strftime('%d') },
716 'DT_HOUR' => sub { localtime->strftime('%H') },
717 'DT_MINUTE' => sub { localtime->strftime('%M') },
718 'DT_SECOND' => sub { localtime->strftime('%S') },
719 'DT_UTC_SIMPLE' => sub { gmtime->strftime('%Y%m%d%H%M%S') },
720 'DT_UTC_YEAR' => sub { gmtime->strftime('%Y') },
721 'DT_UTC_MONTH' => sub { gmtime->strftime('%m') },
722 'DT_UTC_DAY' => sub { gmtime->strftime('%d') },
723 'DT_UTC_HOUR' => sub { gmtime->strftime('%H') },
724 'DT_UTC_MINUTE' => sub { gmtime->strftime('%M') },
725 'DT_UTC_SECOND' => sub { gmtime->strftime('%S') },
726 # 'PICKCHARS'
727 # 'PICKCHARS:'
728 # 'PICKFIELD'
729 # 'NEWPASSWORD'
730 # 'NEWPASSWORD:'
731 # 'PASSWORD_ENC'
732 'HMACOTP' => sub { $_[0]->hmac_otp },
733 'TIMEOTP' => sub { $_[0]->time_otp },
734 'C:' => sub { '' }, # comment
735 # 'BASE'
736 # 'BASE:'
737 # 'CLIPBOARD'
738 # 'CLIPBOARD-SET:'
739 # 'CMD:'
740 );
741
742 ##############################################################################
743
744
745 sub _safe {
746 my $self = shift;
747 $SAFE{$self} = shift if @_;
748 $SAFE{$self};
749 }
750
751 sub _remove_safe { delete $SAFE{$_[0]} }
752
753 sub lock {
754 my $self = shift;
755
756 $self->_safe and return $self;
757
758 my @strings;
759
760 $self->entries(history => 1)->each(sub {
761 push @strings, grep { $_->{protect} } values %{$_->strings}, values %{$_->binaries};
762 });
763
764 $self->_safe(File::KDBX::Safe->new(\@strings));
765
766 return $self;
767 }
768
769
770 sub unlock {
771 my $self = shift;
772 my $safe = $self->_safe or return $self;
773
774 $safe->unlock;
775 $self->_remove_safe;
776
777 return $self;
778 }
779
780
781 sub unlock_scoped {
782 throw 'Programmer error: Cannot call unlock_scoped in void context' if !defined wantarray;
783 my $self = shift;
784 return if !$self->is_locked;
785 require Scope::Guard;
786 my $guard = Scope::Guard->new(sub { $self->lock });
787 $self->unlock;
788 return $guard;
789 }
790
791
792 sub peek {
793 my $self = shift;
794 my $string = shift;
795 my $safe = $self->_safe or return;
796 return $safe->peek($string);
797 }
798
799
800 sub is_locked { !!$_[0]->_safe }
801
802 ##############################################################################
803
804 # sub check {
805 # - Fixer tool. Can repair inconsistencies, including:
806 # - Orphaned binaries... not really a thing anymore since we now distribute binaries amongst entries
807 # - Unused custom icons (OFF, data loss)
808 # - Duplicate icons
809 # - All data types are valid
810 # - date times are correct
811 # - boolean fields
812 # - All UUIDs refer to things that exist
813 # - previous parent group
814 # - recycle bin
815 # - last selected group
816 # - last visible group
817 # - Enforce history size limits (ON)
818 # - Check headers/meta (ON)
819 # - Duplicate deleted objects (ON)
820 # - Duplicate window associations (OFF)
821 # - Header UUIDs match known ciphers/KDFs?
822 # }
823
824
825 sub remove_empty_groups {
826 my $self = shift;
827 my @removed;
828 $self->groups(algorithm => 'dfs')
829 ->where(-true => 'is_empty')
830 ->each(sub { push @removed, $_->remove });
831 return @removed;
832 }
833
834
835 sub remove_unused_icons {
836 my $self = shift;
837 my %icons = map { $_->{uuid} => 0 } @{$self->custom_icons};
838
839 $self->objects->each(sub { ++$icons{$_->custom_icon_uuid // ''} });
840
841 my @removed;
842 push @removed, $self->remove_custom_icon($_) for grep { $icons{$_} == 0 } keys %icons;
843 return @removed;
844 }
845
846
847 sub remove_duplicate_icons {
848 my $self = shift;
849
850 my %seen;
851 my %dup;
852 for my $icon (@{$self->custom_icons}) {
853 my $digest = digest_data('SHA256', $icon->{data});
854 if (my $other = $seen{$digest}) {
855 $dup{$icon->{uuid}} = $other->{uuid};
856 }
857 else {
858 $seen{$digest} = $icon;
859 }
860 }
861
862 my @removed;
863 while (my ($old_uuid, $new_uuid) = each %dup) {
864 $self->objects
865 ->where(custom_icon_uuid => $old_uuid)
866 ->each(sub { $_->custom_icon_uuid($new_uuid) });
867 push @removed, $self->remove_custom_icon($old_uuid);
868 }
869 return @removed;
870 }
871
872
873 sub prune_history {
874 my $self = shift;
875 my %args = @_;
876
877 my $max_items = $args{max_items} // $self->history_max_items // HISTORY_DEFAULT_MAX_ITEMS;
878 my $max_size = $args{max_size} // $self->history_max_size // HISTORY_DEFAULT_MAX_SIZE;
879 my $max_age = $args{max_age} // $self->maintenance_history_days // HISTORY_DEFAULT_MAX_AGE;
880
881 my @removed;
882 $self->entries->each(sub {
883 push @removed, $_->prune_history(
884 max_items => $max_items,
885 max_size => $max_size,
886 max_age => $max_age,
887 );
888 });
889 return @removed;
890 }
891
892
893 sub randomize_seeds {
894 my $self = shift;
895 $self->encryption_iv(random_bytes(16));
896 $self->inner_random_stream_key(random_bytes(64));
897 $self->master_seed(random_bytes(32));
898 $self->stream_start_bytes(random_bytes(32));
899 $self->transform_seed(random_bytes(32));
900 }
901
902 ##############################################################################
903
904
905 sub key {
906 my $self = shift;
907 $KEYS{$self} = File::KDBX::Key->new(@_) if @_;
908 $KEYS{$self};
909 }
910
911
912 sub composite_key {
913 my $self = shift;
914 require File::KDBX::Key::Composite;
915 return File::KDBX::Key::Composite->new(@_);
916 }
917
918
919 sub kdf {
920 my $self = shift;
921 my %args = @_ % 2 == 1 ? (params => shift, @_) : @_;
922
923 my $params = $args{params};
924 my $compat = $args{compatible} // 1;
925
926 $params //= $self->kdf_parameters;
927 $params = {%{$params || {}}};
928
929 if (empty $params || !defined $params->{+KDF_PARAM_UUID}) {
930 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES;
931 }
932 if ($params->{+KDF_PARAM_UUID} eq KDF_UUID_AES) {
933 # AES_CHALLENGE_RESPONSE is equivalent to AES if there are no challenge-response keys, and since
934 # non-KeePassXC implementations don't support challenge-response keys anyway, there's no problem with
935 # always using AES_CHALLENGE_RESPONSE for all KDBX4+ databases.
936 # For compatibility, we should not *write* AES_CHALLENGE_RESPONSE, but the dumper handles that.
937 if ($self->version >= KDBX_VERSION_4_0) {
938 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES_CHALLENGE_RESPONSE;
939 }
940 $params->{+KDF_PARAM_AES_SEED} //= $self->transform_seed;
941 $params->{+KDF_PARAM_AES_ROUNDS} //= $self->transform_rounds;
942 }
943
944 require File::KDBX::KDF;
945 return File::KDBX::KDF->new(%$params);
946 }
947
948 sub transform_seed {
949 my $self = shift;
950 $self->headers->{+HEADER_TRANSFORM_SEED} =
951 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} = shift if @_;
952 $self->headers->{+HEADER_TRANSFORM_SEED} =
953 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} //= random_bytes(32);
954 }
955
956 sub transform_rounds {
957 my $self = shift;
958 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
959 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} = shift if @_;
960 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
961 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} //= 100_000;
962 }
963
964
965 sub cipher {
966 my $self = shift;
967 my %args = @_;
968
969 $args{uuid} //= $self->headers->{+HEADER_CIPHER_ID};
970 $args{iv} //= $self->headers->{+HEADER_ENCRYPTION_IV};
971
972 require File::KDBX::Cipher;
973 return File::KDBX::Cipher->new(%args);
974 }
975
976
977 sub random_stream {
978 my $self = shift;
979 my %args = @_;
980
981 $args{stream_id} //= delete $args{id} // $self->inner_random_stream_id;
982 $args{key} //= $self->inner_random_stream_key;
983
984 require File::KDBX::Cipher;
985 File::KDBX::Cipher->new(%args);
986 }
987
988 sub inner_random_stream_id {
989 my $self = shift;
990 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
991 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} = shift if @_;
992 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
993 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} //= do {
994 my $version = $self->minimum_version;
995 $version < KDBX_VERSION_4_0 ? STREAM_ID_SALSA20 : STREAM_ID_CHACHA20;
996 };
997 }
998
999 sub inner_random_stream_key {
1000 my $self = shift;
1001 if (@_) {
1002 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1003 # trick anyway.
1004 erase \$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
1005 erase \$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
1006 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1007 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} = shift;
1008 }
1009 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1010 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} //= random_bytes(64); # 32
1011 }
1012
1013 #########################################################################################
1014
1015 sub _handle_signal {
1016 my $self = shift;
1017 my $object = shift;
1018 my $type = shift;
1019
1020 my %handlers = (
1021 'entry.added' => \&_handle_object_added,
1022 'group.added' => \&_handle_object_added,
1023 'entry.removed' => \&_handle_object_removed,
1024 'group.removed' => \&_handle_object_removed,
1025 'entry.uuid.changed' => \&_handle_entry_uuid_changed,
1026 'group.uuid.changed' => \&_handle_group_uuid_changed,
1027 );
1028 my $handler = $handlers{$type} or return;
1029 $self->$handler($object, @_);
1030 }
1031
1032 sub _handle_object_added {
1033 my $self = shift;
1034 my $object = shift;
1035 $self->remove_deleted_object($object->uuid);
1036 }
1037
1038 sub _handle_object_removed {
1039 my $self = shift;
1040 my $object = shift;
1041 my $old_uuid = $object->{uuid} // return;
1042
1043 my $meta = $self->meta;
1044 $self->recycle_bin_uuid(UUID_NULL) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
1045 $self->entry_templates_group(UUID_NULL) if $old_uuid eq ($meta->{entry_templates_group} // '');
1046 $self->last_selected_group(UUID_NULL) if $old_uuid eq ($meta->{last_selected_group} // '');
1047 $self->last_top_visible_group(UUID_NULL) if $old_uuid eq ($meta->{last_top_visible_group} // '');
1048
1049 $self->add_deleted_object($old_uuid);
1050 }
1051
1052 sub _handle_entry_uuid_changed {
1053 my $self = shift;
1054 my $object = shift;
1055 my $new_uuid = shift;
1056 my $old_uuid = shift // return;
1057
1058 my $old_pretty = format_uuid($old_uuid);
1059 my $new_pretty = format_uuid($new_uuid);
1060 my $fieldref_match = qr/\{REF:([TUPANI])\@I:\Q$old_pretty\E\}/is;
1061
1062 $self->entries->each(sub {
1063 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1064
1065 for my $string (values %{$_->strings}) {
1066 next if !defined $string->{value} || $string->{value} !~ $fieldref_match;
1067 my $txn = $_->begin_work;
1068 $string->{value} =~ s/$fieldref_match/{REF:$1\@I:$new_pretty}/g;
1069 $txn->commit;
1070 }
1071 });
1072 }
1073
1074 sub _handle_group_uuid_changed {
1075 my $self = shift;
1076 my $object = shift;
1077 my $new_uuid = shift;
1078 my $old_uuid = shift // return;
1079
1080 my $meta = $self->meta;
1081 $self->recycle_bin_uuid($new_uuid) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
1082 $self->entry_templates_group($new_uuid) if $old_uuid eq ($meta->{entry_templates_group} // '');
1083 $self->last_selected_group($new_uuid) if $old_uuid eq ($meta->{last_selected_group} // '');
1084 $self->last_top_visible_group($new_uuid) if $old_uuid eq ($meta->{last_top_visible_group} // '');
1085
1086 $self->groups->each(sub {
1087 $_->last_top_visible_entry($new_uuid) if $old_uuid eq ($_->{last_top_visible_entry} // '');
1088 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1089 });
1090 $self->entries->each(sub {
1091 $_->previous_parent_group($new_uuid) if $old_uuid eq ($_->{previous_parent_group} // '');
1092 });
1093 }
1094
1095 #########################################################################################
1096
1097
1098 #########################################################################################
1099
1100 sub TO_JSON { +{%{$_[0]}} }
1101
1102 1;
1103
1104 __END__
1105
1106 =pod
1107
1108 =encoding UTF-8
1109
1110 =for markdown [![Linux](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml)
1111 [![macOS](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/macos.yml)
1112 [![Windows](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml/badge.svg)](https://github.com/chazmcgarvey/File-KDBX/actions/workflows/windows.yml)
1113
1114 =for HTML <a title="Linux" href="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml"><img src="https://github.com/chazmcgarvey/File-KDBX/actions/workflows/linux.yml/badge.svg"></a>
1115 <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>
1116 <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>
1117
1118 =head1 NAME
1119
1120 File::KDBX - Encrypted database to store secret text and files
1121
1122 =head1 VERSION
1123
1124 version 0.903
1125
1126 =head1 SYNOPSIS
1127
1128 use File::KDBX;
1129
1130 # Create a new database from scratch
1131 my $kdbx = File::KDBX->new;
1132
1133 # Add some objects to the database
1134 my $group = $kdbx->add_group(
1135 name => 'Passwords',
1136 );
1137 my $entry = $group->add_entry(
1138 title => 'My Bank',
1139 username => 'mreynolds',
1140 password => 's3cr3t',
1141 );
1142
1143 # Save the database to the filesystem
1144 $kdbx->dump_file('passwords.kdbx', 'masterpw changeme');
1145
1146 # Load the database from the filesystem into a new database instance
1147 my $kdbx2 = File::KDBX->load_file('passwords.kdbx', 'masterpw changeme');
1148
1149 # Iterate over database entries, print entry titles
1150 $kdbx2->entries->each(sub($entry, @) {
1151 say 'Entry: ', $entry->title;
1152 });
1153
1154 See L</RECIPES> for more examples.
1155
1156 =head1 DESCRIPTION
1157
1158 B<File::KDBX> provides everything you need to work with KDBX databases. A KDBX database is a hierarchical
1159 object database which is commonly used to store secret information securely. It was developed for the KeePass
1160 password safe. See L</"Introduction to KDBX"> for more information about KDBX.
1161
1162 This module lets you query entries, create new entries, delete entries, modify entries and more. The
1163 distribution also includes various parsers and generators for serializing and persisting databases.
1164
1165 The design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
1166 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
1167 that works well in most cases but has a small backlog of bugs and security issues and also does not work with
1168 newer KDBX version 4 files. If you're coming here from the B<File::KeePass> world, you might be interested in
1169 L<File::KeePass::KDBX> that is a drop-in replacement for B<File::KeePass> that uses B<File::KDBX> for storage.
1170
1171 This software is a B<pre-1.0 release>. The interface should be considered pretty stable, but there might be
1172 minor changes up until a 1.0 release. Breaking changes will be noted in the F<Changes> file.
1173
1174 =head2 Features
1175
1176 =over 4
1177
1178 =item *
1179
1180 ☑ Read and write KDBX version 3 - version 4.1
1181
1182 =item *
1183
1184 ☑ Read and write KDB files (requires L<File::KeePass>)
1185
1186 =item *
1187
1188 ☑ Unicode character strings
1189
1190 =item *
1191
1192 ☑ L</"Simple Expression"> Searching
1193
1194 =item *
1195
1196 ☑ L<Placeholders|File::KDBX::Entry/Placeholders> and L<field references|/resolve_reference>
1197
1198 =item *
1199
1200 ☑ L<One-time passwords|File::KDBX::Entry/"One-time Passwords">
1201
1202 =item *
1203
1204 ☑ L<Very secure|/SECURITY>
1205
1206 =item *
1207
1208 ☑ L</"Memory Protection">
1209
1210 =item *
1211
1212 ☑ Challenge-response key components, like L<YubiKey|File::KDBX::Key::YubiKey>
1213
1214 =item *
1215
1216 ☑ Variety of L<key file|File::KDBX::Key::File> types: binary, hexed, hashed, XML v1 and v2
1217
1218 =item *
1219
1220 ☑ Pluggable registration of different kinds of ciphers and key derivation functions
1221
1222 =item *
1223
1224 ☑ Built-in database maintenance functions
1225
1226 =item *
1227
1228 ☑ Pretty fast, with L<XS optimizations|File::KDBX::XS> available
1229
1230 =item *
1231
1232 ☒ Database synchronization / merging (not yet)
1233
1234 =back
1235
1236 =head2 Introduction to KDBX
1237
1238 A KDBX database consists of a tree of I<groups> and I<entries>, with a single I<root> group. Entries can
1239 contain zero or more key-value pairs of I<strings> and zero or more I<binaries> (i.e. octet strings). Groups,
1240 entries, strings and binaries: that's the KDBX vernacular. A small amount of metadata (timestamps, etc.) is
1241 associated with each entry, group and the database as a whole.
1242
1243 You can think of a KDBX database kind of like a file system, where groups are directories, entries are files,
1244 and strings and binaries make up a file's contents.
1245
1246 Databases are typically persisted as encrypted, compressed files. They are usually accessed directly (i.e.
1247 not over a network). The primary focus of this type of database is data security. It is ideal for storing
1248 relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as
1249 have the correct I<master key>. Even if the database file were to be "leaked" to the public Internet, it
1250 should be virtually impossible to crack with a strong key. The KDBX format is most often used by password
1251 managers to store passwords so that users can know a single strong password and not have to reuse passwords
1252 across different websites. See L</SECURITY> for an overview of security considerations.
1253
1254 =head1 ATTRIBUTES
1255
1256 =head2 sig1
1257
1258 =head2 sig2
1259
1260 =head2 version
1261
1262 =head2 headers
1263
1264 =head2 inner_headers
1265
1266 =head2 meta
1267
1268 =head2 binaries
1269
1270 =head2 deleted_objects
1271
1272 Hash of UUIDs for objects that have been deleted. This includes groups, entries and even custom icons.
1273
1274 =head2 raw
1275
1276 Bytes contained within the encrypted layer of a KDBX file. This is only set when using
1277 L<File::KDBX::Loader::Raw>.
1278
1279 =head2 comment
1280
1281 A text string associated with the database. Often unset.
1282
1283 =head2 cipher_id
1284
1285 The UUID of a cipher used to encrypt the database when stored as a file.
1286
1287 See L<File::KDBX::Cipher>.
1288
1289 =head2 compression_flags
1290
1291 Configuration for whether or not and how the database gets compressed. See
1292 L<File::KDBX::Constants/":compression">.
1293
1294 =head2 master_seed
1295
1296 The master seed is a string of 32 random bytes that is used as salt in hashing the master key when loading
1297 and saving the database. If a challenge-response key is used in the master key, the master seed is also the
1298 challenge.
1299
1300 The master seed I<should> be changed each time the database is saved to file.
1301
1302 =head2 transform_seed
1303
1304 The transform seed is a string of 32 random bytes that is used in the key derivation function, either as the
1305 salt or the key (depending on the algorithm).
1306
1307 The transform seed I<should> be changed each time the database is saved to file.
1308
1309 =head2 transform_rounds
1310
1311 The number of rounds or iterations used in the key derivation function. Increasing this number makes loading
1312 and saving the database slower by design in order to make dictionary and brute force attacks more costly.
1313
1314 =head2 encryption_iv
1315
1316 The initialization vector used by the cipher.
1317
1318 The encryption IV I<should> be changed each time the database is saved to file.
1319
1320 =head2 inner_random_stream_key
1321
1322 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1323 within the database.
1324
1325 =head2 stream_start_bytes
1326
1327 A string of 32 random bytes written in the header and encrypted in the body. If the bytes do not match when
1328 loading a file then the wrong master key was used or the file is corrupt. Only KDBX 2 and KDBX 3 files use
1329 this. KDBX 4 files use an improved HMAC method to verify the master key and data integrity of the header and
1330 entire file body.
1331
1332 =head2 inner_random_stream_id
1333
1334 A number indicating the cipher algorithm used to encrypt the protected strings within the database, usually
1335 Salsa20 or ChaCha20. See L<File::KDBX::Constants/":random_stream">.
1336
1337 =head2 kdf_parameters
1338
1339 A hash/dict of key-value pairs used to configure the key derivation function. This is the KDBX4+ way to
1340 configure the KDF, superceding L</transform_seed> and L</transform_rounds>.
1341
1342 =head2 generator
1343
1344 The name of the software used to generate the KDBX file.
1345
1346 =head2 header_hash
1347
1348 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1349
1350 =head2 database_name
1351
1352 Name of the database.
1353
1354 =head2 database_name_changed
1355
1356 Timestamp indicating when the database name was last changed.
1357
1358 =head2 database_description
1359
1360 Description of the database
1361
1362 =head2 database_description_changed
1363
1364 Timestamp indicating when the database description was last changed.
1365
1366 =head2 default_username
1367
1368 When a new entry is created, the I<UserName> string will be populated with this value.
1369
1370 =head2 default_username_changed
1371
1372 Timestamp indicating when the default username was last changed.
1373
1374 =head2 color
1375
1376 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
1377 use this to help users visually distinguish between different databases.
1378
1379 =head2 master_key_changed
1380
1381 Timestamp indicating when the master key was last changed.
1382
1383 =head2 master_key_change_rec
1384
1385 Number of days until the agent should prompt to recommend changing the master key.
1386
1387 =head2 master_key_change_force
1388
1389 Number of days until the agent should prompt to force changing the master key.
1390
1391 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
1392 B<File::KDBX> does NOT enforce it.
1393
1394 =head2 custom_icons
1395
1396 Array of custom icons that can be associated with groups and entries.
1397
1398 This list can be managed with the methods L</add_custom_icon> and L</remove_custom_icon>.
1399
1400 =head2 recycle_bin_enabled
1401
1402 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1403
1404 =head2 recycle_bin_uuid
1405
1406 The UUID of a group used to store thrown-away groups and entries.
1407
1408 =head2 recycle_bin_changed
1409
1410 Timestamp indicating when the recycle bin group was last changed.
1411
1412 =head2 entry_templates_group
1413
1414 The UUID of a group containing template entries used when creating new entries.
1415
1416 =head2 entry_templates_group_changed
1417
1418 Timestamp indicating when the entry templates group was last changed.
1419
1420 =head2 last_selected_group
1421
1422 The UUID of the previously-selected group.
1423
1424 =head2 last_top_visible_group
1425
1426 The UUID of the group visible at the top of the list.
1427
1428 =head2 history_max_items
1429
1430 The maximum number of historical entries that should be kept for each entry. Default is 10.
1431
1432 =head2 history_max_size
1433
1434 The maximum total size (in bytes) that each individual entry's history is allowed to grow. Default is 6 MiB.
1435
1436 =head2 maintenance_history_days
1437
1438 The maximum age (in days) historical entries should be kept. Default it 365.
1439
1440 =head2 settings_changed
1441
1442 Timestamp indicating when the database settings were last updated.
1443
1444 =head2 protect_title
1445
1446 Alias of the L</memory_protection> setting for the I<Title> string.
1447
1448 =head2 protect_username
1449
1450 Alias of the L</memory_protection> setting for the I<UserName> string.
1451
1452 =head2 protect_password
1453
1454 Alias of the L</memory_protection> setting for the I<Password> string.
1455
1456 =head2 protect_url
1457
1458 Alias of the L</memory_protection> setting for the I<URL> string.
1459
1460 =head2 protect_notes
1461
1462 Alias of the L</memory_protection> setting for the I<Notes> string.
1463
1464 =head1 METHODS
1465
1466 =head2 new
1467
1468 $kdbx = File::KDBX->new(%attributes);
1469 $kdbx = File::KDBX->new($kdbx); # copy constructor
1470
1471 Construct a new L<File::KDBX>.
1472
1473 =head2 init
1474
1475 $kdbx = $kdbx->init(%attributes);
1476
1477 Initialize a L<File::KDBX> with a set of attributes. Returns itself to allow method chaining.
1478
1479 This is called by L</new>.
1480
1481 =head2 reset
1482
1483 $kdbx = $kdbx->reset;
1484
1485 Set a L<File::KDBX> to an empty state, ready to load a KDBX file or build a new one. Returns itself to allow
1486 method chaining.
1487
1488 =head2 clone
1489
1490 $kdbx_copy = $kdbx->clone;
1491 $kdbx_copy = File::KDBX->new($kdbx);
1492
1493 Clone a L<File::KDBX>. The clone will be an exact copy and completely independent of the original.
1494
1495 =head2 load
1496
1497 =head2 load_string
1498
1499 =head2 load_file
1500
1501 =head2 load_handle
1502
1503 $kdbx = KDBX::File->load(\$string, $key);
1504 $kdbx = KDBX::File->load(*IO, $key);
1505 $kdbx = KDBX::File->load($filepath, $key);
1506 $kdbx->load(...); # also instance method
1507
1508 $kdbx = File::KDBX->load_string($string, $key);
1509 $kdbx = File::KDBX->load_string(\$string, $key);
1510 $kdbx->load_string(...); # also instance method
1511
1512 $kdbx = File::KDBX->load_file($filepath, $key);
1513 $kdbx->load_file(...); # also instance method
1514
1515 $kdbx = File::KDBX->load_handle($fh, $key);
1516 $kdbx = File::KDBX->load_handle(*IO, $key);
1517 $kdbx->load_handle(...); # also instance method
1518
1519 Load a KDBX file from a string buffer, IO handle or file from a filesystem.
1520
1521 L<File::KDBX::Loader> does the heavy lifting.
1522
1523 =head2 dump
1524
1525 =head2 dump_string
1526
1527 =head2 dump_file
1528
1529 =head2 dump_handle
1530
1531 $kdbx->dump(\$string, $key);
1532 $kdbx->dump(*IO, $key);
1533 $kdbx->dump($filepath, $key);
1534
1535 $kdbx->dump_string(\$string, $key);
1536 \$string = $kdbx->dump_string($key);
1537
1538 $kdbx->dump_file($filepath, $key);
1539
1540 $kdbx->dump_handle($fh, $key);
1541 $kdbx->dump_handle(*IO, $key);
1542
1543 Dump a KDBX file to a string buffer, IO handle or file in a filesystem.
1544
1545 L<File::KDBX::Dumper> does the heavy lifting.
1546
1547 =head2 user_agent_string
1548
1549 $string = $kdbx->user_agent_string;
1550
1551 Get a text string identifying the database client software.
1552
1553 =head2 memory_protection
1554
1555 \%settings = $kdbx->memory_protection
1556 $kdbx->memory_protection(\%settings);
1557
1558 $bool = $kdbx->memory_protection($string_key);
1559 $kdbx->memory_protection($string_key => $bool);
1560
1561 Get or set memory protection settings. This globally (for the whole database) configures whether and which of
1562 the standard strings should be memory-protected. The default setting is to memory-protect only I<Password>
1563 strings.
1564
1565 Memory protection can be toggled individually for each entry string, and individual settings take precedence
1566 over these global settings.
1567
1568 =head2 minimum_version
1569
1570 $version = $kdbx->minimum_version;
1571
1572 Determine the minimum file version required to save a database losslessly. Using certain databases features
1573 might increase this value. For example, setting the KDF to Argon2 will increase the minimum version to at
1574 least C<KDBX_VERSION_4_0> (i.e. C<0x00040000>) because Argon2 was introduced with KDBX4.
1575
1576 This method never returns less than C<KDBX_VERSION_3_1> (i.e. C<0x00030001>). That file version is so
1577 ubiquitous and well-supported, there are seldom reasons to dump in a lesser format nowadays.
1578
1579 B<WARNING:> If you dump a database with a minimum version higher than the current L</version>, the dumper will
1580 typically issue a warning and automatically upgrade the database. This seems like the safest behavior in order
1581 to avoid data loss, but lower versions have the benefit of being compatible with more software. It is possible
1582 to prevent auto-upgrades by explicitly telling the dumper which version to use, but you do run the risk of
1583 data loss. A database will never be automatically downgraded.
1584
1585 =head2 root
1586
1587 $group = $kdbx->root;
1588 $kdbx->root($group);
1589
1590 Get or set a database's root group. You don't necessarily need to explicitly create or set a root group
1591 because it autovivifies when adding entries and groups to the database.
1592
1593 Every database has only a single root group at a time. Some old KDB files might have multiple root groups.
1594 When reading such files, a single implicit root group is created to contain the actual root groups. When
1595 writing to such a format, if the root group looks like it was implicitly created then it won't be written and
1596 the resulting file might have multiple root groups, as it was before loading. This allows working with older
1597 files without changing their written internal structure while still adhering to modern semantics while the
1598 database is opened.
1599
1600 The root group of a KDBX database contains all of the database's entries and other groups. If you replace the
1601 root group, you are essentially replacing the entire database contents with something else.
1602
1603 =head2 trace_lineage
1604
1605 \@lineage = $kdbx->trace_lineage($group);
1606 \@lineage = $kdbx->trace_lineage($group, $base_group);
1607 \@lineage = $kdbx->trace_lineage($entry);
1608 \@lineage = $kdbx->trace_lineage($entry, $base_group);
1609
1610 Get the direct line of ancestors from C<$base_group> (default: the root group) to a group or entry. The
1611 lineage includes the base group but I<not> the target group or entry. Returns C<undef> if the target is not in
1612 the database structure.
1613
1614 =head2 recycle_bin
1615
1616 $group = $kdbx->recycle_bin;
1617 $kdbx->recycle_bin($group);
1618
1619 Get or set the recycle bin group. Returns C<undef> if there is no recycle bin and L</recycle_bin_enabled> is
1620 false, otherwise the current recycle bin or an autovivified recycle bin group is returned.
1621
1622 =head2 entry_templates
1623
1624 $group = $kdbx->entry_templates;
1625 $kdbx->entry_templates($group);
1626
1627 Get or set the entry templates group. May return C<undef> if unset.
1628
1629 =head2 last_selected
1630
1631 $group = $kdbx->last_selected;
1632 $kdbx->last_selected($group);
1633
1634 Get or set the last selected group. May return C<undef> if unset.
1635
1636 =head2 last_top_visible
1637
1638 $group = $kdbx->last_top_visible;
1639 $kdbx->last_top_visible($group);
1640
1641 Get or set the last top visible group. May return C<undef> if unset.
1642
1643 =head2 add_group
1644
1645 $kdbx->add_group($group);
1646 $kdbx->add_group(%group_attributes, %options);
1647
1648 Add a group to a database. This is equivalent to identifying a parent group and calling
1649 L<File::KDBX::Group/add_group> on the parent group, forwarding the arguments. Available options:
1650
1651 =over 4
1652
1653 =item *
1654
1655 C<group> - Group object or group UUID to add the group to (default: root group)
1656
1657 =back
1658
1659 =head2 groups
1660
1661 \&iterator = $kdbx->groups(%options);
1662 \&iterator = $kdbx->groups($base_group, %options);
1663
1664 Get an L<File::KDBX::Iterator> over I<groups> within a database. Options:
1665
1666 =over 4
1667
1668 =item *
1669
1670 C<base> - Only include groups within a base group (same as C<$base_group>) (default: L</root>)
1671
1672 =item *
1673
1674 C<inclusive> - Include the base group in the results (default: true)
1675
1676 =item *
1677
1678 C<algorithm> - Search algorithm, one of C<ids>, C<bfs> or C<dfs> (default: C<ids>)
1679
1680 =back
1681
1682 =head2 add_entry
1683
1684 $kdbx->add_entry($entry, %options);
1685 $kdbx->add_entry(%entry_attributes, %options);
1686
1687 Add a entry to a database. This is equivalent to identifying a parent group and calling
1688 L<File::KDBX::Group/add_entry> on the parent group, forwarding the arguments. Available options:
1689
1690 =over 4
1691
1692 =item *
1693
1694 C<group> - Group object or group UUID to add the entry to (default: root group)
1695
1696 =back
1697
1698 =head2 entries
1699
1700 \&iterator = $kdbx->entries(%options);
1701 \&iterator = $kdbx->entries($base_group, %options);
1702
1703 Get an L<File::KDBX::Iterator> over I<entries> within a database. Supports the same options as L</groups>,
1704 plus some new ones:
1705
1706 =over 4
1707
1708 =item *
1709
1710 C<auto_type> - Only include entries with auto-type enabled (default: false, include all)
1711
1712 =item *
1713
1714 C<searching> - Only include entries within groups with searching enabled (default: false, include all)
1715
1716 =item *
1717
1718 C<history> - Also include historical entries (default: false, include only current entries)
1719
1720 =back
1721
1722 =head2 objects
1723
1724 \&iterator = $kdbx->objects(%options);
1725 \&iterator = $kdbx->objects($base_group, %options);
1726
1727 Get an L<File::KDBX::Iterator> over I<objects> within a database. Groups and entries are considered objects,
1728 so this is essentially a combination of L</groups> and L</entries>. This won't often be useful, but it can be
1729 convenient for maintenance tasks. This method takes the same options as L</groups> and L</entries>.
1730
1731 =head2 custom_icon
1732
1733 \%icon = $kdbx->custom_icon($uuid);
1734 $kdbx->custom_icon($uuid => \%icon);
1735 $kdbx->custom_icon(%icon);
1736 $kdbx->custom_icon(uuid => $value, %icon);
1737
1738 Get or set custom icons.
1739
1740 =head2 custom_icon_data
1741
1742 $image_data = $kdbx->custom_icon_data($uuid);
1743
1744 Get a custom icon image data.
1745
1746 =head2 add_custom_icon
1747
1748 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
1749 $uuid = $kdbx->add_custom_icon(%attributes);
1750
1751 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
1752
1753 =over 4
1754
1755 =item *
1756
1757 C<uuid> - Icon UUID (default: autogenerated)
1758
1759 =item *
1760
1761 C<data> - Image data (same as C<$image_data>)
1762
1763 =item *
1764
1765 C<name> - Name of the icon (text, KDBX4.1+)
1766
1767 =item *
1768
1769 C<last_modification_time> - Just what it says (datetime, KDBX4.1+)
1770
1771 =back
1772
1773 =head2 remove_custom_icon
1774
1775 $kdbx->remove_custom_icon($uuid);
1776
1777 Remove a custom icon.
1778
1779 =head2 custom_data
1780
1781 \%all_data = $kdbx->custom_data;
1782 $kdbx->custom_data(\%all_data);
1783
1784 \%data = $kdbx->custom_data($key);
1785 $kdbx->custom_data($key => \%data);
1786 $kdbx->custom_data(%data);
1787 $kdbx->custom_data(key => $value, %data);
1788
1789 Get and set custom data. Custom data is metadata associated with a database.
1790
1791 Each data item can have a few attributes associated with it.
1792
1793 =over 4
1794
1795 =item *
1796
1797 C<key> - A unique text string identifier used to look up the data item (required)
1798
1799 =item *
1800
1801 C<value> - A text string value (required)
1802
1803 =item *
1804
1805 C<last_modification_time> (optional, KDBX4.1+)
1806
1807 =back
1808
1809 =head2 custom_data_value
1810
1811 $value = $kdbx->custom_data_value($key);
1812
1813 Exactly the same as L</custom_data> except returns just the custom data's value rather than a structure of
1814 attributes. This is a shortcut for:
1815
1816 my $data = $kdbx->custom_data($key);
1817 my $value = defined $data ? $data->{value} : undef;
1818
1819 =head2 public_custom_data
1820
1821 \%all_data = $kdbx->public_custom_data;
1822 $kdbx->public_custom_data(\%all_data);
1823
1824 $value = $kdbx->public_custom_data($key);
1825 $kdbx->public_custom_data($key => $value);
1826
1827 Get and set public custom data. Public custom data is similar to custom data but different in some important
1828 ways. Public custom data:
1829
1830 =over 4
1831
1832 =item *
1833
1834 can store strings, booleans and up to 64-bit integer values (custom data can only store text values)
1835
1836 =item *
1837
1838 is NOT encrypted within a KDBX file (hence the "public" part of the name)
1839
1840 =item *
1841
1842 is a plain hash/dict of key-value pairs with no other associated fields (like modification times)
1843
1844 =back
1845
1846 =head2 add_deleted_object
1847
1848 $kdbx->add_deleted_object($uuid);
1849
1850 Add a UUID to the deleted objects list. This list is used to support automatic database merging.
1851
1852 You typically do not need to call this yourself because the list will be populated automatically as objects
1853 are removed.
1854
1855 =head2 remove_deleted_object
1856
1857 $kdbx->remove_deleted_object($uuid);
1858
1859 Remove a UUID from the deleted objects list. This list is used to support automatic database merging.
1860
1861 You typically do not need to call this yourself because the list will be maintained automatically as objects
1862 are added.
1863
1864 =head2 clear_deleted_objects
1865
1866 Remove all UUIDs from the deleted objects list. This list is used to support automatic database merging, but
1867 if you don't need merging then you can clear deleted objects to reduce the database file size.
1868
1869 =head2 resolve_reference
1870
1871 $string = $kdbx->resolve_reference($reference);
1872 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
1873
1874 Resolve a L<field reference|https://keepass.info/help/base/fieldrefs.html>. A field reference is a kind of
1875 string placeholder. You can use a field reference to refer directly to a standard field within an entry. Field
1876 references are resolved automatically while expanding entry strings (i.e. replacing placeholders), but you can
1877 use this method to resolve on-the-fly references that aren't part of any actual string in the database.
1878
1879 If the reference does not resolve to any field, C<undef> is returned. If the reference resolves to multiple
1880 fields, only the first one is returned (in the same order as iterated by L</entries>). To avoid ambiguity, you
1881 can refer to a specific entry by its UUID.
1882
1883 The syntax of a reference is: C<< {REF:<WantedField>@<SearchIn>:<Text>} >>. C<Text> is a
1884 L</"Simple Expression">. C<WantedField> and C<SearchIn> are both single character codes representing a field:
1885
1886 =over 4
1887
1888 =item *
1889
1890 C<T> - Title
1891
1892 =item *
1893
1894 C<U> - UserName
1895
1896 =item *
1897
1898 C<P> - Password
1899
1900 =item *
1901
1902 C<A> - URL
1903
1904 =item *
1905
1906 C<N> - Notes
1907
1908 =item *
1909
1910 C<I> - UUID
1911
1912 =item *
1913
1914 C<O> - Other custom strings
1915
1916 =back
1917
1918 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
1919
1920 Examples:
1921
1922 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
1923
1924 my $username = $kdbx->resolve_reference('{REF:U@T:"My Bank"}');
1925 # OR the {REF:...} wrapper is optional
1926 my $username = $kdbx->resolve_reference('U@T:"My Bank"');
1927 # OR separate the arguments
1928 my $username = $kdbx->resolve_reference(U => T => '"My Bank"');
1929
1930 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
1931 quotes.
1932
1933 To get the I<Password> string of a specific entry (identified by its UUID):
1934
1935 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
1936
1937 =head2 lock
1938
1939 $kdbx->lock;
1940
1941 Encrypt all protected strings and binaries in a database. The encrypted data is stored in
1942 a L<File::KDBX::Safe> associated with the database and the actual values will be replaced with C<undef> to
1943 indicate their protected state. Returns itself to allow method chaining.
1944
1945 You can call C<lock> on an already-locked database to memory-protect any unprotected strings and binaries
1946 added after the last time the database was locked.
1947
1948 =head2 unlock
1949
1950 $kdbx->unlock;
1951
1952 Decrypt all protected strings and binaries in a database, replacing C<undef> value placeholders with their
1953 actual, unprotected values. Returns itself to allow method chaining.
1954
1955 =head2 unlock_scoped
1956
1957 $guard = $kdbx->unlock_scoped;
1958
1959 Unlock a database temporarily, relocking when the guard is released (typically at the end of a scope). Returns
1960 C<undef> if the database is already unlocked.
1961
1962 See L</lock> and L</unlock>.
1963
1964 Example:
1965
1966 {
1967 my $guard = $kdbx->unlock_scoped;
1968 ...;
1969 }
1970 # $kdbx is now memory-locked
1971
1972 =head2 peek
1973
1974 $string = $kdbx->peek(\%string);
1975 $string = $kdbx->peek(\%binary);
1976
1977 Peek at the value of a protected string or binary without unlocking the whole database. The argument can be
1978 a string or binary hashref as returned by L<File::KDBX::Entry/string> or L<File::KDBX::Entry/binary>.
1979
1980 =head2 is_locked
1981
1982 $bool = $kdbx->is_locked;
1983
1984 Get whether or not a database's contents are in a locked (i.e. memory-protected) state. If this is true, then
1985 some or all of the protected strings and binaries within the database will be unavailable (literally have
1986 C<undef> values) until L</unlock> is called.
1987
1988 =head2 remove_empty_groups
1989
1990 $kdbx->remove_empty_groups;
1991
1992 Remove groups with no subgroups and no entries.
1993
1994 =head2 remove_unused_icons
1995
1996 $kdbx->remove_unused_icons;
1997
1998 Remove icons that are not associated with any entry or group in the database.
1999
2000 =head2 remove_duplicate_icons
2001
2002 $kdbx->remove_duplicate_icons;
2003
2004 Remove duplicate icons as determined by hashing the icon data.
2005
2006 =head2 prune_history
2007
2008 $kdbx->prune_history(%options);
2009
2010 Remove just as many older historical entries as necessary to get under certain limits.
2011
2012 =over 4
2013
2014 =item *
2015
2016 C<max_items> - Maximum number of historical entries to keep (default: value of L</history_max_items>, no limit: -1)
2017
2018 =item *
2019
2020 C<max_size> - Maximum total size (in bytes) of historical entries to keep (default: value of L</history_max_size>, no limit: -1)
2021
2022 =item *
2023
2024 C<max_age> - Maximum age (in days) of historical entries to keep (default: 365, no limit: -1)
2025
2026 =back
2027
2028 =head2 randomize_seeds
2029
2030 $kdbx->randomize_seeds;
2031
2032 Set various keys, seeds and IVs to random values. These values are used by the cryptographic functions that
2033 secure the database when dumped. The attributes that will be randomized are:
2034
2035 =over 4
2036
2037 =item *
2038
2039 L</encryption_iv>
2040
2041 =item *
2042
2043 L</inner_random_stream_key>
2044
2045 =item *
2046
2047 L</master_seed>
2048
2049 =item *
2050
2051 L</stream_start_bytes>
2052
2053 =item *
2054
2055 L</transform_seed>
2056
2057 =back
2058
2059 Randomizing these values has no effect on a loaded database. These are only used when a database is dumped.
2060 You normally do not need to call this method explicitly because the dumper does it explicitly by default.
2061
2062 =head2 key
2063
2064 $key = $kdbx->key;
2065 $key = $kdbx->key($key);
2066 $key = $kdbx->key($primitive);
2067
2068 Get or set a L<File::KDBX::Key>. This is the master key (e.g. a password or a key file that can decrypt
2069 a database). You can also pass a primitive castable to a B<Key>. See L<File::KDBX::Key/new> for an explanation
2070 of what the primitive can be.
2071
2072 You generally don't need to call this directly because you can provide the key directly to the loader or
2073 dumper when loading or dumping a KDBX file.
2074
2075 =head2 composite_key
2076
2077 $key = $kdbx->composite_key($key);
2078 $key = $kdbx->composite_key($primitive);
2079
2080 Construct a L<File::KDBX::Key::Composite> from a B<Key> or primitive. See L<File::KDBX::Key/new> for an
2081 explanation of what the primitive can be. If the primitive does not represent a composite key, it will be
2082 wrapped.
2083
2084 You generally don't need to call this directly. The loader and dumper use it to transform a master key into
2085 a raw encryption key.
2086
2087 =head2 kdf
2088
2089 $kdf = $kdbx->kdf(%options);
2090 $kdf = $kdbx->kdf(\%parameters, %options);
2091
2092 Get a L<File::KDBX::KDF> (key derivation function).
2093
2094 Options:
2095
2096 =over 4
2097
2098 =item *
2099
2100 C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
2101
2102 =back
2103
2104 =head2 cipher
2105
2106 $cipher = $kdbx->cipher(key => $key);
2107 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
2108
2109 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
2110
2111 A key is required. This should be a raw encryption key made up of a fixed number of octets (depending on the
2112 cipher), not a L<File::KDBX::Key> or primitive.
2113
2114 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
2115 C<< $kdbx->headers->{encryption_iv} >>.
2116
2117 You generally don't need to call this directly. The loader and dumper use it to decrypt and encrypt KDBX
2118 files.
2119
2120 =head2 random_stream
2121
2122 $cipher = $kdbx->random_stream;
2123 $cipher = $kdbx->random_stream(id => $stream_id, key => $key);
2124
2125 Get a L<File::KDBX::Cipher::Stream> for decrypting and encrypting protected values.
2126
2127 If not passed, the ID and encryption key comes from C<< $kdbx->headers->{inner_random_stream_id} >> and
2128 C<< $kdbx->headers->{inner_random_stream_key} >> (respectively) for KDBX3 files and from
2129 C<< $kdbx->inner_headers->{inner_random_stream_key} >> and
2130 C<< $kdbx->inner_headers->{inner_random_stream_id} >> (respectively) for KDBX4 files.
2131
2132 You generally don't need to call this directly. The loader and dumper use it to scramble protected strings.
2133
2134 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
2135
2136 =head1 RECIPES
2137
2138 =head2 Create a new database
2139
2140 my $kdbx = File::KDBX->new;
2141
2142 my $group = $kdbx->add_group(name => 'Passwords);
2143 my $entry = $group->add_entry(
2144 title => 'WayneCorp',
2145 username => 'bwayne',
2146 password => 'iambatman',
2147 url => 'https://example.com/login'
2148 );
2149 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
2150
2151 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
2152
2153 =head2 Read an existing database
2154
2155 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
2156 $kdbx->unlock; # cause $entry->password below to be defined
2157
2158 $kdbx->entries->each(sub($entry, @) {
2159 say 'Found password for: ', $entry->title;
2160 say ' Username: ', $entry->username;
2161 say ' Password: ', $entry->password;
2162 });
2163
2164 =head2 Search for entries
2165
2166 my @entries = $kdbx->entries(searching => 1)
2167 ->grep(title => 'WayneCorp')
2168 ->each; # return all matches
2169
2170 The C<searching> option limits results to only entries within groups with searching enabled. Other options are
2171 also available. See L</entries>.
2172
2173 See L</QUERY> for many more query examples.
2174
2175 =head2 Search for entries by auto-type window association
2176
2177 my $window_title = 'WayneCorp - Mozilla Firefox';
2178
2179 my $entries = $kdbx->entries(auto_type => 1)
2180 ->filter(sub {
2181 my ($ata) = grep { $_->{window} =~ /\Q$window_title\E/i } @{$_->auto_type_associations};
2182 return [$_, $ata->{keystroke_sequence}] if $ata;
2183 })
2184 ->each(sub {
2185 my ($entry, $keys) = @$_;
2186 say 'Entry title: ', $entry->title, ', key sequence: ', $keys;
2187 });
2188
2189 Example output:
2190
2191 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
2192
2193 =head2 Remove entries from a database
2194
2195 $kdbx->entries
2196 ->grep(notes => {'=~' => qr/too old/i})
2197 ->each(sub { $_->recycle });
2198
2199 Recycle all entries with the string "too old" appearing in the B<Notes> string.
2200
2201 =head2 Remove empty groups
2202
2203 $kdbx->groups(algorithm => 'dfs')
2204 ->where(-true => 'is_empty')
2205 ->each('remove');
2206
2207 With the search/iteration C<algorithm> set to "dfs", groups will be ordered deepest first and the root group
2208 will be last. This allows removing groups that only contain empty groups.
2209
2210 This can also be done with one call to L</remove_empty_groups>.
2211
2212 =head1 SECURITY
2213
2214 One of the biggest threats to your database security is how easily the encryption key can be brute-forced.
2215 Strong brute-force protection depends on:
2216
2217 =over 4
2218
2219 =item *
2220
2221 Using unguessable passwords, passphrases and key files.
2222
2223 =item *
2224
2225 Using a brute-force resistent key derivation function.
2226
2227 =back
2228
2229 The first factor is up to you. This module does not enforce strong master keys. It is up to you to pick or
2230 generate strong keys.
2231
2232 The KDBX format allows for the key derivation function to be tuned. The idea is that you want each single
2233 brute-foce attempt to be expensive (in terms of time, CPU usage or memory usage), so that making a lot of
2234 attempts (which would be required if you have a strong master key) gets I<really> expensive.
2235
2236 How expensive you want to make each attempt is up to you and can depend on the application.
2237
2238 This and other KDBX-related security issues are covered here more in depth:
2239 L<https://keepass.info/help/base/security.html>
2240
2241 Here are other security risks you should be thinking about:
2242
2243 =head2 Cryptography
2244
2245 This distribution uses the excellent L<CryptX> and L<Crypt::Argon2> packages to handle all crypto-related
2246 functions. As such, a lot of the security depends on the quality of these dependencies. Fortunately these
2247 modules are maintained and appear to have good track records.
2248
2249 The KDBX format has evolved over time to incorporate improved security practices and cryptographic functions.
2250 This package uses the following functions for authentication, hashing, encryption and random number
2251 generation:
2252
2253 =over 4
2254
2255 =item *
2256
2257 AES-128 (legacy)
2258
2259 =item *
2260
2261 AES-256
2262
2263 =item *
2264
2265 Argon2d & Argon2id
2266
2267 =item *
2268
2269 CBC block mode
2270
2271 =item *
2272
2273 HMAC-SHA256
2274
2275 =item *
2276
2277 SHA256
2278
2279 =item *
2280
2281 SHA512
2282
2283 =item *
2284
2285 Salsa20 & ChaCha20
2286
2287 =item *
2288
2289 Twofish
2290
2291 =back
2292
2293 At the time of this writing, I am not aware of any successful attacks against any of these functions. These
2294 are among the most-analyzed and widely-adopted crypto functions available.
2295
2296 The KDBX format allows the body cipher and key derivation function to be configured. If a flaw is discovered
2297 in one of these functions, you can hopefully just switch to a better function without needing to update this
2298 software. A later software release may phase out the use of any functions which are no longer secure.
2299
2300 =head2 Memory Protection
2301
2302 It is not a good idea to keep secret information unencrypted in system memory for longer than is needed. The
2303 address space of your program can generally be read by a user with elevated privileges on the system. If your
2304 system is memory-constrained or goes into a hibernation mode, the contents of your address space could be
2305 written to a disk where it might be persisted for long time.
2306
2307 There might be system-level things you can do to reduce your risk, like using swap encryption and limiting
2308 system access to your program's address space while your program is running.
2309
2310 B<File::KDBX> helps minimize (but not eliminate) risk by keeping secrets encrypted in memory until accessed
2311 and zeroing out memory that holds secrets after they're no longer needed, but it's not a silver bullet.
2312
2313 For one thing, the encryption key is stored in the same address space. If core is dumped, the encryption key
2314 is available to be found out. But at least there is the chance that the encryption key and the encrypted
2315 secrets won't both be paged out together while memory-constrained.
2316
2317 Another problem is that some perls (somewhat notoriously) copy around memory behind the scenes willy nilly,
2318 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
2319 be impossible. The good news is that perls with SvPV copy-on-write (enabled by default beginning with perl
2320 5.20) are much better in this regard. With COW, it's mostly possible to know what operations will cause perl
2321 to copy the memory of a scalar string, and the number of copies will be significantly reduced. There is a unit
2322 test named F<t/memory-protection.t> in this distribution that can be run on POSIX systems to determine how
2323 well B<File::KDBX> memory protection is working.
2324
2325 Memory protection also depends on how your application handles secrets. If your app code is handling scalar
2326 strings with secret information, it's up to you to make sure its memory is zeroed out when no longer needed.
2327 L<File::KDBX::Util/erase> et al. provide some tools to help accomplish this. Or if you're not too concerned
2328 about the risks memory protection is meant to mitigate, then maybe don't worry about it. The security policy
2329 of B<File::KDBX> is to try hard to keep secrets protected while in memory so that your app might claim a high
2330 level of security, in case you care about that.
2331
2332 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
2333
2334 Many systems allow programs to mark unswappable pages. Secret information should ideally be stored in such
2335 pages. You could potentially use L<mlockall(2)> (or equivalent for your system) in your own application to
2336 prevent the entire address space from being swapped.
2337
2338 Some systems provide special syscalls for storing secrets in memory while keeping the encryption key outside
2339 of the program's address space, like C<CryptProtectMemory> for Windows. This could be a good option, though
2340 unfortunately not portable.
2341
2342 =head1 QUERY
2343
2344 To find things in a KDBX database, you should use a filtered iterator. If you have an iterator, such as
2345 returned by L</entries>, L</groups> or even L</objects> you can filter it using L<File::KDBX::Iterator/where>.
2346
2347 my $filtered_entries = $kdbx->entries->where(\&query);
2348
2349 A C<\&query> is just a subroutine that you can either write yourself or have generated for you from either
2350 a L</"Simple Expression"> or L</"Declarative Syntax">. It's easier to have your query generated, so I'll cover
2351 that first.
2352
2353 =head2 Simple Expression
2354
2355 A simple expression is mostly compatible with the KeePass 2 implementation
2356 L<described here|https://keepass.info/help/base/search.html#mode_se>.
2357
2358 An expression is a string with one or more space-separated terms. Terms with spaces can be enclosed in double
2359 quotes. Terms are negated if they are prefixed with a minus sign. A record must match every term on at least
2360 one of the given fields.
2361
2362 So a simple expression is something like what you might type into a search engine. You can generate a simple
2363 expression query using L<File::KDBX::Util/simple_expression_query> or by passing the simple expression as
2364 a B<scalar reference> to C<where>.
2365
2366 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
2367
2368 my $entries = $kdbx->entries->where(\'canyon', qw[title]);
2369
2370 Notice the first argument is a B<scalarref>. This disambiguates a simple expression from other types of
2371 queries covered below.
2372
2373 As mentioned, a simple expression can have multiple terms. This simple expression query matches any entry that
2374 has the words "red" B<and> "canyon" anywhere in the title:
2375
2376 my $entries = $kdbx->entries->where(\'red canyon', qw[title]);
2377
2378 Each term in the simple expression must be found for an entry to match.
2379
2380 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
2381
2382 my $entries = $kdbx->entries->where(\'red -canyon', qw[title]);
2383
2384 To search over multiple fields simultaneously, just list them all. To search for entries with "grocery" (but
2385 not "Foodland") in the title or notes:
2386
2387 my $entries = $kdbx->entries->where(\'grocery -Foodland', qw[title notes]);
2388
2389 The default operator is a case-insensitive regexp match, which is fine for searching text loosely. You can use
2390 just about any binary comparison operator that perl supports. To specify an operator, list it after the simple
2391 expression. For example, to search for any entry that has been used at least five times:
2392
2393 my $entries = $kdbx->entries->where(\5, '>=', qw[usage_count]);
2394
2395 It helps to read it right-to-left, like "usage_count is greater than or equal to 5".
2396
2397 If you find the disambiguating structures to be distracting or confusing, you can also the
2398 L<File::KDBX::Util/simple_expression_query> function as a more intuitive alternative. The following example is
2399 equivalent to the previous:
2400
2401 my $entries = $kdbx->entries->where(simple_expression_query(5, '>=', qw[usage_count]));
2402
2403 =head2 Declarative Syntax
2404
2405 Structuring a declarative query is similar to L<SQL::Abstract/"WHERE CLAUSES">, but you don't have to be
2406 familiar with that module. Just learn by examples here.
2407
2408 To search for all entries in a database titled "My Bank":
2409
2410 my $entries = $kdbx->entries->where({ title => 'My Bank' });
2411
2412 The query here is C<< { title => 'My Bank' } >>. A hashref can contain key-value pairs where the key is an
2413 attribute of the thing being searched for (in this case an entry) and the value is what you want the thing's
2414 attribute to be to consider it a match. In this case, the attribute we're using as our match criteria is
2415 L<File::KDBX::Entry/title>, a text field. If an entry has its title attribute equal to "My Bank", it's
2416 a match.
2417
2418 A hashref can contain multiple attributes. The search candidate will be a match if I<all> of the specified
2419 attributes are equal to their respective values. For example, to search for all entries with a particular URL
2420 B<AND> username:
2421
2422 my $entries = $kdbx->entries->where({
2423 url => 'https://example.com',
2424 username => 'neo',
2425 });
2426
2427 To search for entries matching I<any> criteria, just change the hashref to an arrayref. To search for entries
2428 with a particular URL B<OR> username:
2429
2430 my $entries = $kdbx->entries->where([ # <-- Notice the square bracket
2431 url => 'https://example.com',
2432 username => 'neo',
2433 ]);
2434
2435 You can use different operators to test different types of attributes. The L<File::KDBX::Entry/icon_id>
2436 attribute is a number, so we should use a number comparison operator. To find entries using the smartphone
2437 icon:
2438
2439 my $entries = $kdbx->entries->where({
2440 icon_id => { '==', ICON_SMARTPHONE },
2441 });
2442
2443 Note: L<File::KDBX::Constants/ICON_SMARTPHONE> is just a constant from L<File::KDBX::Constants>. It isn't
2444 special to this example or to queries generally. We could have just used a literal number.
2445
2446 The important thing to notice here is how we wrapped the condition in another arrayref with a single key-value
2447 pair where the key is the name of an operator and the value is the thing to match against. The supported
2448 operators are:
2449
2450 =over 4
2451
2452 =item *
2453
2454 C<eq> - String equal
2455
2456 =item *
2457
2458 C<ne> - String not equal
2459
2460 =item *
2461
2462 C<lt> - String less than
2463
2464 =item *
2465
2466 C<gt> - String greater than
2467
2468 =item *
2469
2470 C<le> - String less than or equal
2471
2472 =item *
2473
2474 C<ge> - String greater than or equal
2475
2476 =item *
2477
2478 C<==> - Number equal
2479
2480 =item *
2481
2482 C<!=> - Number not equal
2483
2484 =item *
2485
2486 C<< < >> - Number less than
2487
2488 =item *
2489
2490 C<< > >> - Number greater than
2491
2492 =item *
2493
2494 C<< <= >> - Number less than or equal
2495
2496 =item *
2497
2498 C<< >= >> - Number less than or equal
2499
2500 =item *
2501
2502 C<=~> - String match regular expression
2503
2504 =item *
2505
2506 C<!~> - String does not match regular expression
2507
2508 =item *
2509
2510 C<!> - Boolean false
2511
2512 =item *
2513
2514 C<!!> - Boolean true
2515
2516 =back
2517
2518 Other special operators:
2519
2520 =over 4
2521
2522 =item *
2523
2524 C<-true> - Boolean true
2525
2526 =item *
2527
2528 C<-false> - Boolean false
2529
2530 =item *
2531
2532 C<-not> - Boolean false (alias for C<-false>)
2533
2534 =item *
2535
2536 C<-defined> - Is defined
2537
2538 =item *
2539
2540 C<-undef> - Is not defined
2541
2542 =item *
2543
2544 C<-empty> - Is empty
2545
2546 =item *
2547
2548 C<-nonempty> - Is not empty
2549
2550 =item *
2551
2552 C<-or> - Logical or
2553
2554 =item *
2555
2556 C<-and> - Logical and
2557
2558 =back
2559
2560 Let's see another example using an explicit operator. To find all groups except one in particular (identified
2561 by its L<File::KDBX::Group/uuid>), we can use the C<ne> (string not equal) operator:
2562
2563 my $groups = $kdbx->groups->where(
2564 uuid => {
2565 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
2566 },
2567 );
2568
2569 Note: L<File::KDBX::Util/uuid> is a little utility function to convert a UUID in its pretty form into bytes.
2570 This utility function isn't special to this example or to queries generally. It could have been written with
2571 a literal such as C<"\x59\x6f\x75\x20\x61...">, but that's harder to read.
2572
2573 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2574
2575 Notice also that we didn't wrap the query in hashref curly-braces or arrayref square-braces. Those are
2576 optional. By default it will only match ALL attributes (as if there were curly-braces).
2577
2578 Testing the truthiness of an attribute is a little bit different because it isn't a binary operation. To find
2579 all entries with the password quality check disabled:
2580
2581 my $entries = $kdbx->entries->where('!' => 'quality_check');
2582
2583 This time the string after the operator is the attribute name rather than a value to compare the attribute
2584 against. To test that a boolean value is true, use the C<!!> operator (or C<-true> if C<!!> seems a little too
2585 weird for your taste):
2586
2587 my $entries = $kdbx->entries->where('!!' => 'quality_check');
2588 my $entries = $kdbx->entries->where(-true => 'quality_check'); # same thing
2589
2590 Yes, there is also a C<-false> and a C<-not> if you prefer one of those over C<!>. C<-false> and C<-not>
2591 (along with C<-true>) are also special in that you can use them to invert the logic of a subquery. These are
2592 logically equivalent:
2593
2594 my $entries = $kdbx->entries->where(-not => { title => 'My Bank' });
2595 my $entries = $kdbx->entries->where(title => { 'ne' => 'My Bank' });
2596
2597 These special operators become more useful when combined with two more special operators: C<-and> and C<-or>.
2598 With these, it is possible to construct more interesting queries with groups of logic. For example:
2599
2600 my $entries = $kdbx->entries->where({
2601 title => { '=~', qr/bank/ },
2602 -not => {
2603 -or => {
2604 notes => { '=~', qr/business/ },
2605 icon_id => { '==', ICON_TRASHCAN_FULL },
2606 },
2607 },
2608 });
2609
2610 In English, find entries where the word "bank" appears anywhere in the title but also do not have either the
2611 word "business" in the notes or are using the full trashcan icon.
2612
2613 =head2 Subroutine Query
2614
2615 Lastly, as mentioned at the top, you can ignore all this and write your own subroutine. Your subroutine will
2616 be called once for each object being searched over. The subroutine should match the candidate against whatever
2617 criteria you want and return true if it matches or false to skip. To do this, just pass your subroutine
2618 coderef to C<where>.
2619
2620 To review the different types of queries, these are all equivalent to find all entries in the database titled
2621 "My Bank":
2622
2623 my $entries = $kdbx->entries->where(\'"My Bank"', 'eq', qw[title]); # simple expression
2624 my $entries = $kdbx->entries->where(title => 'My Bank'); # declarative syntax
2625 my $entries = $kdbx->entries->where(sub { $_->title eq 'My Bank' }); # subroutine query
2626
2627 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2628
2629 All of these query mechanisms described in this section are just tools, each with its own set of limitations.
2630 If the tools are getting in your way, you can of course iterate over the contents of a database and implement
2631 your own query logic, like this:
2632
2633 my $entries = $kdbx->entries;
2634 while (my $entry = $entries->next) {
2635 if (wanted($entry)) {
2636 do_something($entry);
2637 }
2638 else {
2639 ...
2640 }
2641 }
2642
2643 =head2 Iteration
2644
2645 Iterators are the built-in way to navigate or walk the database tree. You get an iterator from L</entries>,
2646 L</groups> and L</objects>. You can specify the search algorithm to iterate over objects in different orders
2647 using the C<algorithm> option, which can be one of these L<constants|File::KDBX::Constants/":iteration">:
2648
2649 =over 4
2650
2651 =item *
2652
2653 C<ITERATION_IDS> - Iterative deepening search (default)
2654
2655 =item *
2656
2657 C<ITERATION_DFS> - Depth-first search
2658
2659 =item *
2660
2661 C<ITERATION_BFS> - Breadth-first search
2662
2663 =back
2664
2665 When iterating over objects generically, groups always precede their direct entries (if any). When the
2666 C<history> option is used, current entries always precede historical entries.
2667
2668 If you have a database tree like this:
2669
2670 Database
2671 - Root
2672 - Group1
2673 - EntryA
2674 - Group2
2675 - EntryB
2676 - Group3
2677 - EntryC
2678
2679 =over 4
2680
2681 =item *
2682
2683 IDS order of groups is: Root, Group1, Group2, Group3
2684
2685 =item *
2686
2687 IDS order of entries is: EntryA, EntryB, EntryC
2688
2689 =item *
2690
2691 IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC
2692
2693 =item *
2694
2695 DFS order of groups is: Group2, Group1, Group3, Root
2696
2697 =item *
2698
2699 DFS order of entries is: EntryB, EntryA, EntryC
2700
2701 =item *
2702
2703 DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root
2704
2705 =item *
2706
2707 BFS order of groups is: Root, Group1, Group3, Group2
2708
2709 =item *
2710
2711 BFS order of entries is: EntryA, EntryC, EntryB
2712
2713 =item *
2714
2715 BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB
2716
2717 =back
2718
2719 =head1 SYNCHRONIZING
2720
2721 B<TODO> - This is a planned feature, not yet implemented.
2722
2723 =head1 ERRORS
2724
2725 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
2726 mechanisms. Fatal errors are propagated using L<perlfunc/"die LIST"> and non-fatal errors (a.k.a. warnings)
2727 are propagated using L<perlfunc/"warn LIST"> while adhering to perl's L<warnings> system. If you're already
2728 familiar with these mechanisms, you can skip this section.
2729
2730 You can catch fatal errors using L<perlfunc/"eval BLOCK"> (or something like L<Try::Tiny>) and non-fatal
2731 errors using C<$SIG{__WARN__}> (see L<perlvar/%SIG>). Examples:
2732
2733 use File::KDBX::Error qw(error);
2734
2735 my $key = ''; # uh oh
2736 eval {
2737 $kdbx->load_file('whatever.kdbx', $key);
2738 };
2739 if (my $error = error($@)) {
2740 handle_missing_key($error) if $error->type eq 'key.missing';
2741 $error->throw;
2742 }
2743
2744 or using C<Try::Tiny>:
2745
2746 try {
2747 $kdbx->load_file('whatever.kdbx', $key);
2748 }
2749 catch {
2750 handle_error($_);
2751 };
2752
2753 Catching non-fatal errors:
2754
2755 my @warnings;
2756 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2757
2758 $kdbx->load_file('whatever.kdbx', $key);
2759
2760 handle_warnings(@warnings) if @warnings;
2761
2762 By default perl prints warnings to C<STDERR> if you don't catch them. If you don't want to catch them and also
2763 don't want them printed to C<STDERR>, you can suppress them lexically (perl v5.28 or higher required):
2764
2765 {
2766 no warnings 'File::KDBX';
2767 ...
2768 }
2769
2770 or locally:
2771
2772 {
2773 local $File::KDBX::WARNINGS = 0;
2774 ...
2775 }
2776
2777 or globally in your program:
2778
2779 $File::KDBX::WARNINGS = 0;
2780
2781 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2782
2783 =head1 ENVIRONMENT
2784
2785 This software will alter its behavior depending on the value of certain environment variables:
2786
2787 =over 4
2788
2789 =item *
2790
2791 C<PERL_FILE_KDBX_XS> - Do not use L<File::KDBX::XS> if false (default: true)
2792
2793 =item *
2794
2795 C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
2796
2797 =item *
2798
2799 C<NO_FORK> - Do not fork if true (default: false)
2800
2801 =back
2802
2803 =head1 SEE ALSO
2804
2805 =over 4
2806
2807 =item *
2808
2809 L<KeePass Password Safe|https://keepass.info/> - The original KeePass
2810
2811 =item *
2812
2813 L<KeePassXC|https://keepassxc.org/> - Cross-Platform Password Manager written in C++
2814
2815 =item *
2816
2817 L<File::KeePass> has overlapping functionality. It's good but has a backlog of some pretty critical bugs and lacks support for newer KDBX features.
2818
2819 =back
2820
2821 =head1 BUGS
2822
2823 Please report any bugs or feature requests on the bugtracker website
2824 L<https://github.com/chazmcgarvey/File-KDBX/issues>
2825
2826 When submitting a bug or request, please include a test-file or a
2827 patch to an existing test-file that illustrates the bug or desired
2828 feature.
2829
2830 =head1 AUTHOR
2831
2832 Charles McGarvey <ccm@cpan.org>
2833
2834 =head1 COPYRIGHT AND LICENSE
2835
2836 This software is copyright (c) 2022 by Charles McGarvey.
2837
2838 This is free software; you can redistribute it and/or modify it under
2839 the same terms as the Perl 5 programming language system itself.
2840
2841 =cut
This page took 0.210116 seconds and 4 git commands to generate.