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