]> Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX.pm
Add function for creating class attributes
[chaz/p5-File-KDBX] / lib / File / KDBX.pm
1 package File::KDBX;
2 # ABSTRACT: Encrypted databases to store secret text and files
3
4 use warnings;
5 use strict;
6
7 use Crypt::PRNG qw(random_bytes);
8 use Devel::GlobalDestruction;
9 use File::KDBX::Constants qw(:all);
10 use File::KDBX::Error;
11 use File::KDBX::Safe;
12 use File::KDBX::Util qw(:class :coercion :empty :uuid :search erase simple_expression_query snakify);
13 use Hash::Util::FieldHash qw(fieldhashes);
14 use List::Util qw(any);
15 use Ref::Util qw(is_ref is_arrayref is_plain_hashref);
16 use Scalar::Util qw(blessed);
17 use Time::Piece;
18 use boolean;
19 use namespace::clean;
20
21 our $VERSION = '999.999'; # VERSION
22 our $WARNINGS = 1;
23
24 fieldhashes \my (%SAFE, %KEYS);
25
26 =method new
27
28 $kdbx = File::KDBX->new(%attributes);
29 $kdbx = File::KDBX->new($kdbx); # copy constructor
30
31 Construct a new L<File::KDBX>.
32
33 =cut
34
35 sub new {
36 my $class = shift;
37
38 # copy constructor
39 return $_[0]->clone if @_ == 1 && blessed $_[0] && $_[0]->isa($class);
40
41 my $self = bless {}, $class;
42 $self->init(@_);
43 $self->_set_default_attributes if empty $self;
44 return $self;
45 }
46
47 sub DESTROY { local ($., $@, $!, $^E, $?); !in_global_destruction and $_[0]->reset }
48
49 =method init
50
51 $kdbx = $kdbx->init(%attributes);
52
53 Initialize a L<File::KDBX> with a new set of attributes. Returns itself to allow method chaining.
54
55 This is called by L</new>.
56
57 =cut
58
59 sub init {
60 my $self = shift;
61 my %args = @_;
62
63 @$self{keys %args} = values %args;
64
65 return $self;
66 }
67
68 =method reset
69
70 $kdbx = $kdbx->reset;
71
72 Set a L<File::KDBX> to an empty state, ready to load a KDBX file or build a new one. Returns itself to allow
73 method chaining.
74
75 =cut
76
77 sub reset {
78 my $self = shift;
79 erase $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
80 erase $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
81 erase $self->{raw};
82 %$self = ();
83 $self->_remove_safe;
84 return $self;
85 }
86
87 =method clone
88
89 $kdbx_copy = $kdbx->clone;
90 $kdbx_copy = File::KDBX->new($kdbx);
91
92 Clone a L<File::KDBX>. The clone will be an exact copy and completely independent of the original.
93
94 =cut
95
96 sub clone {
97 my $self = shift;
98 require Storable;
99 return Storable::dclone($self);
100 }
101
102 sub STORABLE_freeze {
103 my $self = shift;
104 my $cloning = shift;
105
106 my $copy = {%$self};
107
108 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
109 }
110
111 sub STORABLE_thaw {
112 my $self = shift;
113 my $cloning = shift;
114 shift;
115 my $clone = shift;
116 my $key = shift;
117 my $safe = shift;
118
119 @$self{keys %$clone} = values %$clone;
120 $KEYS{$self} = $key;
121 $SAFE{$self} = $safe;
122
123 for my $object (@{$self->all_groups}, @{$self->all_entries(history => 1)}) {
124 $object->kdbx($self);
125 }
126 }
127
128 ##############################################################################
129
130 =method load
131
132 =method load_string
133
134 =method load_file
135
136 =method load_handle
137
138 $kdbx = KDBX::File->load(\$string, $key);
139 $kdbx = KDBX::File->load(*IO, $key);
140 $kdbx = KDBX::File->load($filepath, $key);
141 $kdbx->load(...); # also instance method
142
143 $kdbx = File::KDBX->load_string($string, $key);
144 $kdbx = File::KDBX->load_string(\$string, $key);
145 $kdbx->load_string(...); # also instance method
146
147 $kdbx = File::KDBX->load_file($filepath, $key);
148 $kdbx->load_file(...); # also instance method
149
150 $kdbx = File::KDBX->load_handle($fh, $key);
151 $kdbx = File::KDBX->load_handle(*IO, $key);
152 $kdbx->load_handle(...); # also instance method
153
154 Load a KDBX file from a string buffer, IO handle or file from a filesystem.
155
156 L<File::KDBX::Loader> does the heavy lifting.
157
158 =cut
159
160 sub load { shift->_loader->load(@_) }
161 sub load_string { shift->_loader->load_string(@_) }
162 sub load_file { shift->_loader->load_file(@_) }
163 sub load_handle { shift->_loader->load_handle(@_) }
164
165 sub _loader {
166 my $self = shift;
167 $self = $self->new if !ref $self;
168 require File::KDBX::Loader;
169 File::KDBX::Loader->new(kdbx => $self);
170 }
171
172 =method dump
173
174 =method dump_string
175
176 =method dump_file
177
178 =method dump_handle
179
180 $kdbx->dump(\$string, $key);
181 $kdbx->dump(*IO, $key);
182 $kdbx->dump($filepath, $key);
183
184 $kdbx->dump_string(\$string, $key);
185 \$string = $kdbx->dump_string($key);
186
187 $kdbx->dump_file($filepath, $key);
188
189 $kdbx->dump_handle($fh, $key);
190 $kdbx->dump_handle(*IO, $key);
191
192 Dump a KDBX file to a string buffer, IO handle or file in a filesystem.
193
194 L<File::KDBX::Dumper> does the heavy lifting.
195
196 =cut
197
198 sub dump { shift->_dumper->dump(@_) }
199 sub dump_string { shift->_dumper->dump_string(@_) }
200 sub dump_file { shift->_dumper->dump_file(@_) }
201 sub dump_handle { shift->_dumper->dump_handle(@_) }
202
203 sub _dumper {
204 my $self = shift;
205 $self = $self->new if !ref $self;
206 require File::KDBX::Dumper;
207 File::KDBX::Dumper->new(kdbx => $self);
208 }
209
210 ##############################################################################
211
212 =method user_agent_string
213
214 $string = $kdbx->user_agent_string;
215
216 Get a text string identifying the database client software.
217
218 =cut
219
220 sub user_agent_string {
221 require Config;
222 sprintf('%s/%s (%s/%s; %s/%s; %s)',
223 __PACKAGE__, $VERSION, @Config::Config{qw(package version osname osvers archname)});
224 }
225
226 my %ATTRS = (
227 sig1 => [KDBX_SIG1, coerce => \&to_number],
228 sig2 => [KDBX_SIG2_2, coerce => \&to_number],
229 version => [KDBX_VERSION_3_1, coerce => \&to_number],
230 headers => [{}],
231 inner_headers => [{}],
232 meta => [{}],
233 binaries => [{}],
234 deleted_objects => [{}],
235 raw => [undef, coerce => \&to_string],
236 );
237 my %ATTRS_HEADERS = (
238 HEADER_COMMENT() => ['', coerce => \&to_string],
239 HEADER_CIPHER_ID() => [CIPHER_UUID_CHACHA20, coerce => \&to_uuid],
240 HEADER_COMPRESSION_FLAGS() => [COMPRESSION_GZIP, coerce => sub { compression($_[0]) }],
241 HEADER_MASTER_SEED() => [sub { random_bytes(32) }, coerce => \&to_string],
242 # HEADER_TRANSFORM_SEED() => sub { random_bytes(32) },
243 # HEADER_TRANSFORM_ROUNDS() => 100_000,
244 HEADER_ENCRYPTION_IV() => [sub { random_bytes(16) }, coerce => \&to_string],
245 # HEADER_INNER_RANDOM_STREAM_KEY() => sub { random_bytes(32) }, # 64?
246 HEADER_STREAM_START_BYTES() => [sub { random_bytes(32) }, coerce => \&to_string],
247 # HEADER_INNER_RANDOM_STREAM_ID() => STREAM_ID_CHACHA20,
248 HEADER_KDF_PARAMETERS() => [sub {
249 +{
250 KDF_PARAM_UUID() => KDF_UUID_AES,
251 KDF_PARAM_AES_ROUNDS() => $_[0]->headers->{+HEADER_TRANSFORM_ROUNDS} // KDF_DEFAULT_AES_ROUNDS,
252 KDF_PARAM_AES_SEED() => $_[0]->headers->{+HEADER_TRANSFORM_SEED} // random_bytes(32),
253 };
254 }],
255 # HEADER_PUBLIC_CUSTOM_DATA() => sub { +{} },
256 );
257 my %ATTRS_META = (
258 generator => ['', coerce => \&to_string],
259 header_hash => ['', coerce => \&to_string],
260 database_name => ['', coerce => \&to_string],
261 database_name_changed => [sub { gmtime }, coerce => \&to_time],
262 database_description => ['', coerce => \&to_string],
263 database_description_changed => [sub { gmtime }, coerce => \&to_time],
264 default_username => ['', coerce => \&to_string],
265 default_username_changed => [sub { gmtime }, coerce => \&to_time],
266 maintenance_history_days => [0, coerce => \&to_number],
267 color => ['', coerce => \&to_string],
268 master_key_changed => [sub { gmtime }, coerce => \&to_time],
269 master_key_change_rec => [-1, coerce => \&to_number],
270 master_key_change_force => [-1, coerce => \&to_number],
271 # memory_protection => {},
272 custom_icons => [{}],
273 recycle_bin_enabled => [true, coerce => \&to_bool],
274 recycle_bin_uuid => ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", coerce => \&to_uuid],
275 recycle_bin_changed => [sub { gmtime }, coerce => \&to_time],
276 entry_templates_group => ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", coerce => \&to_uuid],
277 entry_templates_group_changed => [sub { gmtime }, coerce => \&to_time],
278 last_selected_group => ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", coerce => \&to_uuid],
279 last_top_visible_group => ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", coerce => \&to_uuid],
280 history_max_items => [HISTORY_DEFAULT_MAX_ITEMS, coerce => \&to_number],
281 history_max_size => [HISTORY_DEFAULT_MAX_SIZE, coerce => \&to_number],
282 settings_changed => [sub { gmtime }, coerce => \&to_time],
283 # binaries => {},
284 # custom_data => {},
285 );
286 my %ATTRS_MEMORY_PROTECTION = (
287 protect_title => [false, coerce => \&to_bool],
288 protect_username => [false, coerce => \&to_bool],
289 protect_password => [true, coerce => \&to_bool],
290 protect_url => [false, coerce => \&to_bool],
291 protect_notes => [false, coerce => \&to_bool],
292 # auto_enable_visual_hiding => false,
293 );
294
295 while (my ($attr, $default) = each %ATTRS) {
296 has $attr => @$default;
297 }
298 while (my ($attr, $default) = each %ATTRS_HEADERS) {
299 has $attr => @$default, store => 'headers';
300 }
301 while (my ($attr, $default) = each %ATTRS_META) {
302 has $attr => @$default, store => 'meta';
303 }
304 while (my ($attr, $default) = each %ATTRS_MEMORY_PROTECTION) {
305 has $attr => @$default, store => 'memory_protection';
306 }
307
308 my @ATTRS_OTHER = (
309 HEADER_TRANSFORM_SEED,
310 HEADER_TRANSFORM_ROUNDS,
311 HEADER_INNER_RANDOM_STREAM_KEY,
312 HEADER_INNER_RANDOM_STREAM_ID,
313 HEADER_PUBLIC_CUSTOM_DATA,
314 );
315 sub _set_default_attributes {
316 my $self = shift;
317 $self->$_ for keys %ATTRS, keys %ATTRS_HEADERS, keys %ATTRS_META, keys %ATTRS_MEMORY_PROTECTION,
318 @ATTRS_OTHER;
319 }
320
321 =method memory_protection
322
323 \%settings = $kdbx->memory_protection
324 $kdbx->memory_protection(\%settings);
325
326 $bool = $kdbx->memory_protection($string_key);
327 $kdbx->memory_protection($string_key => $bool);
328
329 Get or set memory protection settings. This globally (for the whole database) configures whether and which of
330 the standard strings should be memory-protected. The default setting is to memory-protect only I<Password>
331 strings.
332
333 Memory protection can be toggled individually for each entry string, and individual settings take precedence
334 over these global settings.
335
336 =cut
337
338 sub memory_protection {
339 my $self = shift;
340 $self->{meta}{memory_protection} = shift if @_ == 1 && is_plain_hashref($_[0]);
341 return $self->{meta}{memory_protection} //= {} if !@_;
342
343 my $string_key = shift;
344 my $key = 'protect_' . lc($string_key);
345
346 $self->meta->{memory_protection}{$key} = shift if @_;
347 $self->meta->{memory_protection}{$key};
348 }
349
350 =method minimum_version
351
352 $version = $kdbx->minimum_version;
353
354 Determine the minimum file version required to save a database losslessly. Using certain databases features
355 might increase this value. For example, setting the KDF to Argon2 will increase the minimum version to at
356 least C<KDBX_VERSION_4_0> (i.e. C<0x00040000>) because Argon2 was introduced with KDBX4.
357
358 This method never returns less than C<KDBX_VERSION_3_1> (i.e. C<0x00030001>). That file version is so
359 ubiquitious and well-supported, there are seldom reasons to dump in a lesser format nowadays.
360
361 B<WARNING:> If you dump a database with a minimum version higher than the current L</version>, the dumper will
362 typically issue a warning and automatically upgrade the database. This seems like the safest behavior in order
363 to avoid data loss, but lower versions have the benefit of being compatible with more software. It is possible
364 to prevent auto-upgrades by explicitly telling the dumper which version to use, but you do run the risk of
365 data loss. A database will never be automatically downgraded.
366
367 =cut
368
369 sub minimum_version {
370 my $self = shift;
371
372 return KDBX_VERSION_4_1 if any {
373 nonempty $_->{last_modification_time}
374 } values %{$self->custom_data};
375
376 return KDBX_VERSION_4_1 if any {
377 nonempty $_->{name} || nonempty $_->{last_modification_time}
378 } values %{$self->custom_icons};
379
380 return KDBX_VERSION_4_1 if any {
381 nonempty $_->previous_parent_group || nonempty $_->tags ||
382 any { nonempty $_->{last_modification_time} } values %{$_->custom_data}
383 } @{$self->all_groups};
384
385 return KDBX_VERSION_4_1 if any {
386 nonempty $_->previous_parent_group || (defined $_->quality_check && !$_->quality_check) ||
387 any { nonempty $_->{last_modification_time} } values %{$_->custom_data}
388 } @{$self->all_entries(history => 1)};
389
390 return KDBX_VERSION_4_0 if $self->kdf->uuid ne KDF_UUID_AES;
391
392 return KDBX_VERSION_4_0 if nonempty $self->public_custom_data;
393
394 return KDBX_VERSION_4_0 if any {
395 nonempty $_->custom_data
396 } @{$self->all_groups}, @{$self->all_entries(history => 1)};
397
398 return KDBX_VERSION_3_1;
399 }
400
401 ##############################################################################
402
403 =method add_group
404
405 $kdbx->add_group($group, %options);
406 $kdbx->add_group(%group_attributes, %options);
407
408 Add a group to a database. This is equivalent to identifying a parent group and calling
409 L<File::KDBX::Group/add_group> on the parent group, forwarding the arguments. Available options:
410
411 =for :list
412 * C<group> (aka C<parent>) - Group (object or group UUID) to add the group to (default: root group)
413
414 =cut
415
416 sub add_group {
417 my $self = shift;
418 my $group = @_ % 2 == 1 ? shift : undef;
419 my %args = @_;
420
421 # find the right group to add the group to
422 my $parent = delete $args{group} // delete $args{parent} // $self->root;
423 ($parent) = $self->find_groups({uuid => $parent}) if !ref $parent;
424 $parent or throw 'Invalid group';
425
426 return $parent->add_group(defined $group ? $group : (), %args, kdbx => $self);
427 }
428
429 sub _wrap_group {
430 my $self = shift;
431 my $group = shift;
432 require File::KDBX::Group;
433 return File::KDBX::Group->wrap($group, $self);
434 }
435
436 =method root
437
438 $group = $kdbx->root;
439 $kdbx->root($group);
440
441 Get or set a database's root group. You don't necessarily need to explicitly create or set a root group
442 because it autovivifies when adding entries and groups to the database.
443
444 Every database has only a single root group at a time. Some old KDB files might have multiple root groups.
445 When reading such files, a single implicit root group is created to contain the other explicit groups. When
446 writing to such a format, if the root group looks like it was implicitly created then it won't be written and
447 the resulting file might have multiple root groups. This allows working with older files without changing
448 their written internal structure while still adhering to modern semantics while the database is opened.
449
450 B<WARNING:> The root group of a KDBX database contains all of the database's entries and other groups. If you
451 replace the root group, you are essentially replacing the entire database contents with something else.
452
453 =cut
454
455 sub root {
456 my $self = shift;
457 if (@_) {
458 $self->{root} = $self->_wrap_group(@_);
459 $self->{root}->kdbx($self);
460 }
461 $self->{root} //= $self->_implicit_root;
462 return $self->_wrap_group($self->{root});
463 }
464
465 sub _kpx_groups {
466 my $self = shift;
467 return [] if !$self->{root};
468 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
469 }
470
471 sub _has_implicit_root {
472 my $self = shift;
473 my $root = $self->root;
474 my $temp = __PACKAGE__->_implicit_root;
475 # If an implicit root group has been changed in any significant way, it is no longer implicit.
476 return $root->name eq $temp->name &&
477 $root->is_expanded ^ $temp->is_expanded &&
478 $root->notes eq $temp->notes &&
479 !@{$root->entries} &&
480 !defined $root->custom_icon_uuid &&
481 !keys %{$root->custom_data} &&
482 $root->icon_id == $temp->icon_id &&
483 $root->expires ^ $temp->expires &&
484 $root->default_auto_type_sequence eq $temp->default_auto_type_sequence &&
485 !defined $root->enable_auto_type &&
486 !defined $root->enable_searching;
487 }
488
489 sub _implicit_root {
490 my $self = shift;
491 require File::KDBX::Group;
492 return File::KDBX::Group->new(
493 name => 'Root',
494 is_expanded => true,
495 notes => 'Added as an implicit root group by '.__PACKAGE__.'.',
496 ref $self ? (kdbx => $self) : (),
497 );
498 }
499
500 =method all_groups
501
502 \@groups = $kdbx->all_groups(%options);
503 \@groups = $kdbx->all_groups($base_group, %options);
504
505 Get all groups deeply in a database, or all groups within a specified base group, in a flat array. Supported
506 options:
507
508 =for :list
509 * C<base> - Only include groups within a base group (same as C<$base_group>) (default: root)
510 * C<include_base> - Include the base group in the results (default: true)
511
512 =cut
513
514 sub all_groups {
515 my $self = shift;
516 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
517 my $base = $args{base} // $self->root;
518
519 my @groups = $args{include_base} // 1 ? $self->_wrap_group($base) : ();
520
521 for my $subgroup (@{$base->{groups} || []}) {
522 my $more = $self->all_groups($subgroup);
523 push @groups, @$more;
524 }
525
526 return \@groups;
527 }
528
529 =method trace_lineage
530
531 \@lineage = $kdbx->trace_lineage($group);
532 \@lineage = $kdbx->trace_lineage($group, $base_group);
533 \@lineage = $kdbx->trace_lineage($entry);
534 \@lineage = $kdbx->trace_lineage($entry, $base_group);
535
536 Get the direct line of ancestors from C<$base_group> (default: the root group) to a group or entry. The
537 lineage includes the base group but I<not> the target group or entry. Returns C<undef> if the target is not in
538 the database structure.
539
540 =cut
541
542 sub trace_lineage {
543 my $self = shift;
544 my $object = shift;
545 return $object->lineage(@_);
546 }
547
548 sub _trace_lineage {
549 my $self = shift;
550 my $object = shift;
551 my @lineage = @_;
552
553 push @lineage, $self->root if !@lineage;
554 my $base = $lineage[-1] or return [];
555
556 my $uuid = $object->uuid;
557 return \@lineage if any { $_->uuid eq $uuid } @{$base->groups || []}, @{$base->entries || []};
558
559 for my $subgroup (@{$base->groups || []}) {
560 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
561 return $result if $result;
562 }
563 }
564
565 =method find_groups
566
567 @groups = $kdbx->find_groups($query, %options);
568
569 Find all groups deeply that match to a query. Options are the same as for L</all_groups>.
570
571 See L</QUERY> for a description of what C<$query> can be.
572
573 =cut
574
575 sub find_groups {
576 my $self = shift;
577 my $query = shift or throw 'Must provide a query';
578 my %args = @_;
579 my %all_groups = (
580 base => $args{base},
581 include_base => $args{include_base},
582 );
583 return @{search($self->all_groups(%all_groups), is_arrayref($query) ? @$query : $query)};
584 }
585
586 sub remove {
587 my $self = shift;
588 my $object = shift;
589 }
590
591 ##############################################################################
592
593 =method add_entry
594
595 $kdbx->add_entry($entry, %options);
596 $kdbx->add_entry(%entry_attributes, %options);
597
598 Add a entry to a database. This is equivalent to identifying a parent group and calling
599 L<File::KDBX::Group/add_entry> on the parent group, forwarding the arguments. Available options:
600
601 =for :list
602 * C<group> (aka C<parent>) - Group (object or group UUID) to add the entry to (default: root group)
603
604 =cut
605
606 sub add_entry {
607 my $self = shift;
608 my $entry = @_ % 2 == 1 ? shift : undef;
609 my %args = @_;
610
611 # find the right group to add the entry to
612 my $parent = delete $args{group} // delete $args{parent} // $self->root;
613 ($parent) = $self->find_groups({uuid => $parent}) if !ref $parent;
614 $parent or throw 'Invalid group';
615
616 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx => $self);
617 }
618
619 sub _wrap_entry {
620 my $self = shift;
621 my $entry = shift;
622 require File::KDBX::Entry;
623 return File::KDBX::Entry->wrap($entry, $self);
624 }
625
626 =method all_entries
627
628 \@entries = $kdbx->all_entries(%options);
629 \@entries = $kdbx->all_entries($base_group, %options);
630
631 Get entries deeply in a database, in a flat array. Supported options:
632
633 =for :list
634 * C<base> - Only include entries within a base group (same as C<$base_group>) (default: root)
635 * C<auto_type> - Only include entries with auto-type enabled (default: false, include all)
636 * C<search> - Only include entries within groups with search enabled (default: false, include all)
637 * C<history> - Also include historical entries (default: false, include only active entries)
638
639 =cut
640
641 sub all_entries {
642 my $self = shift;
643 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
644
645 my $base = $args{base} // $self->root;
646 my $history = $args{history};
647 my $search = $args{search};
648 my $auto_type = $args{auto_type};
649
650 my $enable_auto_type = $base->{enable_auto_type} // true;
651 my $enable_searching = $base->{enable_searching} // true;
652
653 my @entries;
654 if ((!$search || $enable_searching) && (!$auto_type || $enable_auto_type)) {
655 push @entries,
656 map { $self->_wrap_entry($_) }
657 grep { !$auto_type || $_->{auto_type}{enabled} }
658 map { $_, $history ? @{$_->{history} || []} : () }
659 @{$base->{entries} || []};
660 }
661
662 for my $subgroup (@{$base->{groups} || []}) {
663 my $more = $self->all_entries($subgroup,
664 auto_type => $auto_type,
665 search => $search,
666 history => $history,
667 );
668 push @entries, @$more;
669 }
670
671 return \@entries;
672 }
673
674 =method find_entries
675
676 =method find_entries_simple
677
678 @entries = $kdbx->find_entries($query, %options);
679
680 @entries = $kdbx->find_entries_simple($expression, \@fields, %options);
681 @entries = $kdbx->find_entries_simple($expression, $operator, \@fields, %options);
682
683 Find all entries deeply that match a query. Options are the same as for L</all_entries>.
684
685 See L</QUERY> for a description of what C<$query> can be.
686
687 =cut
688
689 sub find_entries {
690 my $self = shift;
691 my $query = shift or throw 'Must provide a query';
692 my %args = @_;
693 my %all_entries = (
694 base => $args{base},
695 auto_type => $args{auto_type},
696 search => $args{search},
697 history => $args{history},
698 );
699 my $limit = delete $args{limit};
700 if (defined $limit) {
701 return @{search_limited($self->all_entries(%all_entries), is_arrayref($query) ? @$query : $query, $limit)};
702 }
703 else {
704 return @{search($self->all_entries(%all_entries), is_arrayref($query) ? @$query : $query)};
705 }
706 }
707
708 sub find_entries_simple {
709 my $self = shift;
710 my $text = shift;
711 my $op = @_ && !is_ref($_[0]) ? shift : undef;
712 my $fields = shift;
713 is_arrayref($fields) or throw q{Usage: find_entries_simple($expression, [$op,] \@fields)};
714 return $self->find_entries([\$text, $op, $fields], @_);
715 }
716
717 ##############################################################################
718
719 =method custom_icon
720
721 \%icon = $kdbx->custom_icon($uuid);
722 $kdbx->custom_icon($uuid => \%icon);
723 $kdbx->custom_icon(%icon);
724 $kdbx->custom_icon(uuid => $value, %icon);
725
726
727 =cut
728
729 sub custom_icon {
730 my $self = shift;
731 my %args = @_ == 2 ? (uuid => shift, value => shift)
732 : @_ % 2 == 1 ? (uuid => shift, @_) : @_;
733
734 if (!$args{key} && !$args{value}) {
735 my %standard = (key => 1, value => 1, last_modification_time => 1);
736 my @other_keys = grep { !$standard{$_} } keys %args;
737 if (@other_keys == 1) {
738 my $key = $args{key} = $other_keys[0];
739 $args{value} = delete $args{$key};
740 }
741 }
742
743 my $key = $args{key} or throw 'Must provide a custom_icons key to access';
744
745 return $self->{meta}{custom_icons}{$key} = $args{value} if is_plain_hashref($args{value});
746
747 while (my ($field, $value) = each %args) {
748 $self->{meta}{custom_icons}{$key}{$field} = $value;
749 }
750 return $self->{meta}{custom_icons}{$key};
751 }
752
753 =method custom_icon_data
754
755 $image_data = $kdbx->custom_icon_data($uuid);
756
757 Get a custom icon.
758
759 =cut
760
761 sub custom_icon_data {
762 my $self = shift;
763 my $uuid = shift // return;
764 return if !exists $self->custom_icons->{$uuid};
765 return $self->custom_icons->{$uuid}{data};
766 }
767
768 =method add_custom_icon
769
770 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
771
772 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
773
774 =for :list
775 * C<uuid> - Icon UUID
776 * C<name> - Name of the icon (text, KDBX4.1+)
777 * C<last_modification_time> - Just what it says (datetime, KDBX4.1+)
778
779 =cut
780
781 sub add_custom_icon {
782 my $self = shift;
783 my $img = shift or throw 'Must provide image data';
784 my %args = @_;
785
786 my $uuid = $args{uuid} // generate_uuid(sub { !$self->custom_icons->{$_} });
787 $self->custom_icons->{$uuid} = {
788 @_,
789 uuid => $uuid,
790 data => $img,
791 };
792 return $uuid;
793 }
794
795 =method remove_custom_icon
796
797 $kdbx->remove_custom_icon($uuid);
798
799 Remove a custom icon.
800
801 =cut
802
803 sub remove_custom_icon {
804 my $self = shift;
805 my $uuid = shift;
806 delete $self->custom_icons->{$uuid};
807 }
808
809 ##############################################################################
810
811 =method custom_data
812
813 \%all_data = $kdbx->custom_data;
814 $kdbx->custom_data(\%all_data);
815
816 \%data = $kdbx->custom_data($key);
817 $kdbx->custom_data($key => \%data);
818 $kdbx->custom_data(%data);
819 $kdbx->custom_data(key => $value, %data);
820
821 Get and set custom data. Custom data is metadata associated with a database.
822
823 Each data item can have a few attributes associated with it.
824
825 =for :list
826 * C<key> - A unique text string identifier used to look up the data item (required)
827 * C<value> - A text string value (required)
828 * C<last_modification_time> (optional, KDBX4.1+)
829
830 =cut
831
832 sub custom_data {
833 my $self = shift;
834 $self->{meta}{custom_data} = shift if @_ == 1 && is_plain_hashref($_[0]);
835 return $self->{meta}{custom_data} //= {} if !@_;
836
837 my %args = @_ == 2 ? (key => shift, value => shift)
838 : @_ % 2 == 1 ? (key => shift, @_) : @_;
839
840 if (!$args{key} && !$args{value}) {
841 my %standard = (key => 1, value => 1, last_modification_time => 1);
842 my @other_keys = grep { !$standard{$_} } keys %args;
843 if (@other_keys == 1) {
844 my $key = $args{key} = $other_keys[0];
845 $args{value} = delete $args{$key};
846 }
847 }
848
849 my $key = $args{key} or throw 'Must provide a custom_data key to access';
850
851 return $self->{meta}{custom_data}{$key} = $args{value} if is_plain_hashref($args{value});
852
853 while (my ($field, $value) = each %args) {
854 $self->{meta}{custom_data}{$key}{$field} = $value;
855 }
856 return $self->{meta}{custom_data}{$key};
857 }
858
859 =method custom_data_value
860
861 $value = $kdbx->custom_data_value($key);
862
863 Exactly the same as L</custom_data> except returns just the custom data's value rather than a structure of
864 attributes. This is a shortcut for:
865
866 my $data = $kdbx->custom_data($key);
867 my $value = defined $data ? $data->{value} : undef;
868
869 =cut
870
871 sub custom_data_value {
872 my $self = shift;
873 my $data = $self->custom_data(@_) // return;
874 return $data->{value};
875 }
876
877 =method public_custom_data
878
879 \%all_data = $kdbx->public_custom_data;
880 $kdbx->public_custom_data(\%all_data);
881
882 $value = $kdbx->public_custom_data($key);
883 $kdbx->public_custom_data($key => $value);
884
885 Get and set public custom data. Public custom data is similar to custom data but different in some important
886 ways. Public custom data:
887
888 =for :list
889 * can store strings, booleans and up to 64-bit integer values (custom data can only store text values)
890 * is NOT encrypted within a KDBX file (hence the "public" part of the name)
891 * is a plain hash/dict of key-value pairs with no other associated fields (like modification times)
892
893 =cut
894
895 sub public_custom_data {
896 my $self = shift;
897 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} = shift if @_ == 1 && is_plain_hashref($_[0]);
898 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} //= {} if !@_;
899
900 my $key = shift or throw 'Must provide a public_custom_data key to access';
901 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key} = shift if @_;
902 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key};
903 }
904
905 ##############################################################################
906
907 # TODO
908
909 # sub merge_to {
910 # my $self = shift;
911 # my $other = shift;
912 # my %options = @_; # prefer_old / prefer_new
913 # $other->merge_from($self);
914 # }
915
916 # sub merge_from {
917 # my $self = shift;
918 # my $other = shift;
919
920 # die 'Not implemented';
921 # }
922
923 ##############################################################################
924
925 =method resolve_reference
926
927 $string = $kdbx->resolve_reference($reference);
928 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
929
930 Resolve a L<field reference|https://keepass.info/help/base/fieldrefs.html>. A field reference is a kind of
931 string placeholder. You can use a field reference to refer directly to a standard field within an entry. Field
932 references are resolved automatically while expanding entry strings (i.e. replacing placeholders), but you can
933 use this method to resolve on-the-fly references that aren't part of any actual string in the database.
934
935 If the reference does not resolve to any field, C<undef> is returned. If the reference resolves to multiple
936 fields, only the first one is returned (in the same order as L</all_entries>). To avoid ambiguity, you can
937 refer to a specific entry by its UUID.
938
939 The syntax of a reference is: C<< {REF:<WantedField>@<SearchIn>:<Text>} >>. C<Text> is a
940 L</"Simple Expression">. C<WantedField> and C<SearchIn> are both single character codes representing a field:
941
942 =for :list
943 * C<T> - Title
944 * C<U> - UserName
945 * C<P> - Password
946 * C<A> - URL
947 * C<N> - Notes
948 * C<I> - UUID
949 * C<O> - Other custom strings
950
951 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
952
953 Examples:
954
955 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
956
957 my $username = $kdbx->resolve_reference('{REF:U@T:"My Bank"}');
958 # OR the {REF:...} wrapper is optional
959 my $username = $kdbx->resolve_reference('U@T:"My Bank"');
960 # OR separate the arguments
961 my $username = $kdbx->resolve_reference(U => T => '"My Bank"');
962
963 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
964 quotes.
965
966 To get the I<Password> string of a specific entry (identified by its UUID):
967
968 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
969
970 =cut
971
972 sub resolve_reference {
973 my $self = shift;
974 my $wanted = shift // return;
975 my $search_in = shift;
976 my $text = shift;
977
978 if (!defined $text) {
979 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
980 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
981 }
982 $wanted && $search_in && nonempty($text) or return;
983
984 my %fields = (
985 T => 'expanded_title',
986 U => 'expanded_username',
987 P => 'expanded_password',
988 A => 'expanded_url',
989 N => 'expanded_notes',
990 I => 'uuid',
991 O => 'other_strings',
992 );
993 $wanted = $fields{$wanted} or return;
994 $search_in = $fields{$search_in} or return;
995
996 my $query = $search_in eq 'uuid' ? query($search_in => uuid($text))
997 : simple_expression_query($text, '=~', $search_in);
998
999 my ($entry) = $self->find_entries($query, limit => 1);
1000 $entry or return;
1001
1002 return $entry->$wanted;
1003 }
1004
1005 our %PLACEHOLDERS = (
1006 # placeholder => sub { my ($entry, $arg) = @_; ... };
1007 'TITLE' => sub { $_[0]->expanded_title },
1008 'USERNAME' => sub { $_[0]->expanded_username },
1009 'PASSWORD' => sub { $_[0]->expanded_password },
1010 'NOTES' => sub { $_[0]->expanded_notes },
1011 'S:' => sub { $_[0]->string_value($_[1]) },
1012 'URL' => sub { $_[0]->expanded_url },
1013 'URL:RMVSCM' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1014 'URL:WITHOUTSCHEME' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1015 'URL:SCM' => sub { (split_url($_[0]->url))[0] },
1016 'URL:SCHEME' => sub { (split_url($_[0]->url))[0] }, # non-standard
1017 'URL:HOST' => sub { (split_url($_[0]->url))[2] },
1018 'URL:PORT' => sub { (split_url($_[0]->url))[3] },
1019 'URL:PATH' => sub { (split_url($_[0]->url))[4] },
1020 'URL:QUERY' => sub { (split_url($_[0]->url))[5] },
1021 'URL:HASH' => sub { (split_url($_[0]->url))[6] }, # non-standard
1022 'URL:FRAGMENT' => sub { (split_url($_[0]->url))[6] }, # non-standard
1023 'URL:USERINFO' => sub { (split_url($_[0]->url))[1] },
1024 'URL:USERNAME' => sub { (split_url($_[0]->url))[7] },
1025 'URL:PASSWORD' => sub { (split_url($_[0]->url))[8] },
1026 'UUID' => sub { local $_ = format_uuid($_[0]->uuid); s/-//g; $_ },
1027 'REF:' => sub { $_[0]->kdbx->resolve_reference($_[1]) },
1028 'INTERNETEXPLORER' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('iexplore') },
1029 'FIREFOX' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('firefox') },
1030 'GOOGLECHROME' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('google-chrome') },
1031 'OPERA' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('opera') },
1032 'SAFARI' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('safari') },
1033 'APPDIR' => sub { load_optional('FindBin'); $FindBin::Bin },
1034 'GROUP' => sub { my $p = $_[0]->parent; $p ? $p->name : undef },
1035 'GROUP_PATH' => sub { $_[0]->path },
1036 'GROUP_NOTES' => sub { my $p = $_[0]->parent; $p ? $p->notes : undef },
1037 # 'GROUP_SEL'
1038 # 'GROUP_SEL_PATH'
1039 # 'GROUP_SEL_NOTES'
1040 # 'DB_PATH'
1041 # 'DB_DIR'
1042 # 'DB_NAME'
1043 # 'DB_BASENAME'
1044 # 'DB_EXT'
1045 'ENV:' => sub { $ENV{$_[1]} },
1046 'ENV_DIRSEP' => sub { load_optional('File::Spec')->catfile('', '') },
1047 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
1048 # 'T-REPLACE-RX:'
1049 # 'T-CONV:'
1050 'DT_SIMPLE' => sub { localtime->strftime('%Y%m%d%H%M%S') },
1051 'DT_YEAR' => sub { localtime->strftime('%Y') },
1052 'DT_MONTH' => sub { localtime->strftime('%m') },
1053 'DT_DAY' => sub { localtime->strftime('%d') },
1054 'DT_HOUR' => sub { localtime->strftime('%H') },
1055 'DT_MINUTE' => sub { localtime->strftime('%M') },
1056 'DT_SECOND' => sub { localtime->strftime('%S') },
1057 'DT_UTC_SIMPLE' => sub { gmtime->strftime('%Y%m%d%H%M%S') },
1058 'DT_UTC_YEAR' => sub { gmtime->strftime('%Y') },
1059 'DT_UTC_MONTH' => sub { gmtime->strftime('%m') },
1060 'DT_UTC_DAY' => sub { gmtime->strftime('%d') },
1061 'DT_UTC_HOUR' => sub { gmtime->strftime('%H') },
1062 'DT_UTC_MINUTE' => sub { gmtime->strftime('%M') },
1063 'DT_UTC_SECOND' => sub { gmtime->strftime('%S') },
1064 # 'PICKCHARS'
1065 # 'PICKCHARS:'
1066 # 'PICKFIELD'
1067 # 'NEWPASSWORD'
1068 # 'NEWPASSWORD:'
1069 # 'PASSWORD_ENC'
1070 'HMACOTP' => sub { $_[0]->hmac_otp },
1071 'TIMEOTP' => sub { $_[0]->time_otp },
1072 'C:' => sub { '' }, # comment
1073 # 'BASE'
1074 # 'BASE:'
1075 # 'CLIPBOARD'
1076 # 'CLIPBOARD-SET:'
1077 # 'CMD:'
1078 );
1079
1080 ##############################################################################
1081
1082 =method lock
1083
1084 $kdbx->lock;
1085
1086 Encrypt all protected strings in a database. The encrypted strings are stored in a L<File::KDBX::Safe>
1087 associated with the database and the actual strings will be replaced with C<undef> to indicate their protected
1088 state. Returns itself to allow method chaining.
1089
1090 =cut
1091
1092 sub _safe {
1093 my $self = shift;
1094 $SAFE{$self} = shift if @_;
1095 $SAFE{$self};
1096 }
1097
1098 sub _remove_safe { delete $SAFE{$_[0]} }
1099
1100 sub lock {
1101 my $self = shift;
1102
1103 $self->_safe and return $self;
1104
1105 my @strings;
1106
1107 my $entries = $self->all_entries(history => 1);
1108 for my $entry (@$entries) {
1109 push @strings, grep { $_->{protect} } values %{$entry->{strings} || {}};
1110 }
1111
1112 $self->_safe(File::KDBX::Safe->new(\@strings));
1113
1114 return $self;
1115 }
1116
1117 =method unlock
1118
1119 $kdbx->unlock;
1120
1121 Decrypt all protected strings in a database, replacing C<undef> placeholders with unprotected values. Returns
1122 itself to allow method chaining.
1123
1124 =cut
1125
1126 sub unlock {
1127 my $self = shift;
1128 my $safe = $self->_safe or return $self;
1129
1130 $safe->unlock;
1131 $self->_remove_safe;
1132
1133 return $self;
1134 }
1135
1136 =method unlock_scoped
1137
1138 $guard = $kdbx->unlock_scoped;
1139
1140 Unlock a database temporarily, relocking when the guard is released (typically at the end of a scope). Returns
1141 C<undef> if the database is already unlocked.
1142
1143 See L</lock> and L</unlock>.
1144
1145 =cut
1146
1147 sub unlock_scoped {
1148 throw 'Programmer error: Cannot call unlock_scoped in void context' if !defined wantarray;
1149 my $self = shift;
1150 return if !$self->is_locked;
1151 require Scope::Guard;
1152 my $guard = Scope::Guard->new(sub { $self->lock });
1153 $self->unlock;
1154 return $guard;
1155 }
1156
1157 =method peek
1158
1159 $string = $kdbx->peek(\%string);
1160 $string = $kdbx->peek(\%binary);
1161
1162 Peek at the value of a protected string or binary without unlocking the whole database. The argument can be
1163 a string or binary hashref as returned by L<File::KDBX::Entry/string> or L<File::KDBX::Entry/binary>.
1164
1165 =cut
1166
1167 sub peek {
1168 my $self = shift;
1169 my $string = shift;
1170 my $safe = $self->_safe or return;
1171 return $safe->peek($string);
1172 }
1173
1174 =method is_locked
1175
1176 $bool = $kdbx->is_locked;
1177
1178 Get whether or not a database's strings are memory-protected. If this is true, then some or all of the
1179 protected strings within the database will be unavailable (literally have C<undef> values) until L</unlock> is
1180 called.
1181
1182 =cut
1183
1184 sub is_locked { $_[0]->_safe ? 1 : 0 }
1185
1186 ##############################################################################
1187
1188 =method randomize_seeds
1189
1190 $kdbx->randomize_seeds;
1191
1192 Set various keys, seeds and IVs to random values. These values are used by the cryptographic functions that
1193 secure the database when dumped. The attributes that will be randomized are:
1194
1195 =for :list
1196 * L</encryption_iv>
1197 * L</inner_random_stream_key>
1198 * L</master_seed>
1199 * L</stream_start_bytes>
1200 * L</transform_seed>
1201
1202 Randomizing these values has no effect on a loaded database. These are only used when a database is dumped.
1203 You normally do not need to call this method explicitly because the dumper does it explicitly by default.
1204
1205 =cut
1206
1207 sub randomize_seeds {
1208 my $self = shift;
1209 $self->encryption_iv(random_bytes(16));
1210 $self->inner_random_stream_key(random_bytes(64));
1211 $self->master_seed(random_bytes(32));
1212 $self->stream_start_bytes(random_bytes(32));
1213 $self->transform_seed(random_bytes(32));
1214 }
1215
1216 ##############################################################################
1217
1218 =method key
1219
1220 $key = $kdbx->key;
1221 $key = $kdbx->key($key);
1222 $key = $kdbx->key($primitive);
1223
1224 Get or set a L<File::KDBX::Key>. This is the master key (i.e. a password or a key file that can decrypt
1225 a database). See L<File::KDBX::Key/new> for an explanation of what the primitive can be.
1226
1227 You generally don't need to call this directly because you can provide the key directly to the loader or
1228 dumper when loading or saving a KDBX file.
1229
1230 =cut
1231
1232 sub key {
1233 my $self = shift;
1234 $KEYS{$self} = File::KDBX::Key->new(@_) if @_;
1235 $KEYS{$self};
1236 }
1237
1238 =method composite_key
1239
1240 $key = $kdbx->composite_key($key);
1241 $key = $kdbx->composite_key($primitive);
1242
1243 Construct a L<File::KDBX::Key::Composite> from a primitive. See L<File::KDBX::Key/new> for an explanation of
1244 what the primitive can be. If the primitive does not represent a composite key, it will be wrapped.
1245
1246 You generally don't need to call this directly. The parser and writer use it to transform a master key into
1247 a raw encryption key.
1248
1249 =cut
1250
1251 sub composite_key {
1252 my $self = shift;
1253 require File::KDBX::Key::Composite;
1254 return File::KDBX::Key::Composite->new(@_);
1255 }
1256
1257 =method kdf
1258
1259 $kdf = $kdbx->kdf(%options);
1260 $kdf = $kdbx->kdf(\%parameters, %options);
1261
1262 Get a L<File::KDBX::KDF> (key derivation function).
1263
1264 Options:
1265
1266 =for :list
1267 * C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
1268
1269 =cut
1270
1271 sub kdf {
1272 my $self = shift;
1273 my %args = @_ % 2 == 1 ? (params => shift, @_) : @_;
1274
1275 my $params = $args{params};
1276 my $compat = $args{compatible} // 1;
1277
1278 $params //= $self->kdf_parameters;
1279 $params = {%{$params || {}}};
1280
1281 if (empty $params || !defined $params->{+KDF_PARAM_UUID}) {
1282 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES;
1283 }
1284 if ($params->{+KDF_PARAM_UUID} eq KDF_UUID_AES) {
1285 # AES_CHALLENGE_RESPONSE is equivalent to AES if there are no challenge-response keys, and since
1286 # non-KeePassXC implementations don't support challenge-response keys anyway, there's no problem with
1287 # always using AES_CHALLENGE_RESPONSE for all KDBX4+ databases.
1288 # For compatibility, we should not *write* AES_CHALLENGE_RESPONSE, but the dumper handles that.
1289 if ($self->version >= KDBX_VERSION_4_0) {
1290 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES_CHALLENGE_RESPONSE;
1291 }
1292 $params->{+KDF_PARAM_AES_SEED} //= $self->transform_seed;
1293 $params->{+KDF_PARAM_AES_ROUNDS} //= $self->transform_rounds;
1294 }
1295
1296 require File::KDBX::KDF;
1297 return File::KDBX::KDF->new(%$params);
1298 }
1299
1300 sub transform_seed {
1301 my $self = shift;
1302 $self->headers->{+HEADER_TRANSFORM_SEED} =
1303 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} = shift if @_;
1304 $self->headers->{+HEADER_TRANSFORM_SEED} =
1305 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} //= random_bytes(32);
1306 }
1307
1308 sub transform_rounds {
1309 my $self = shift;
1310 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1311 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} = shift if @_;
1312 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1313 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} //= 100_000;
1314 }
1315
1316 =method cipher
1317
1318 $cipher = $kdbx->cipher(key => $key);
1319 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
1320
1321 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
1322
1323 A key is required. This should be a raw encryption key made up of a fixed number of octets (depending on the
1324 cipher), not a L<File::KDBX::Key> or primitive.
1325
1326 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
1327 C<< $kdbx->headers->{encryption_iv} >>.
1328
1329 You generally don't need to call this directly. The parser and writer use it to decrypt and encrypt KDBX
1330 files.
1331
1332 =cut
1333
1334 sub cipher {
1335 my $self = shift;
1336 my %args = @_;
1337
1338 $args{uuid} //= $self->headers->{+HEADER_CIPHER_ID};
1339 $args{iv} //= $self->headers->{+HEADER_ENCRYPTION_IV};
1340
1341 require File::KDBX::Cipher;
1342 return File::KDBX::Cipher->new(%args);
1343 }
1344
1345 =method random_stream
1346
1347 $cipher = $kdbx->random_stream;
1348 $cipher = $kdbx->random_stream(id => $stream_id, key => $key);
1349
1350 Get a L<File::KDBX::Cipher::Stream> for decrypting and encrypting protected values.
1351
1352 If not passed, the ID and encryption key comes from C<< $kdbx->headers->{inner_random_stream_id} >> and
1353 C<< $kdbx->headers->{inner_random_stream_key} >> (respectively) for KDBX3 files and from
1354 C<< $kdbx->inner_headers->{inner_random_stream_key} >> and
1355 C<< $kdbx->inner_headers->{inner_random_stream_id} >> (respectively) for KDBX4 files.
1356
1357 You generally don't need to call this directly. The parser and writer use it to scramble protected strings.
1358
1359 =cut
1360
1361 sub random_stream {
1362 my $self = shift;
1363 my %args = @_;
1364
1365 $args{stream_id} //= delete $args{id} // $self->inner_random_stream_id;
1366 $args{key} //= $self->inner_random_stream_key;
1367
1368 require File::KDBX::Cipher;
1369 File::KDBX::Cipher->new(%args);
1370 }
1371
1372 sub inner_random_stream_id {
1373 my $self = shift;
1374 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1375 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} = shift if @_;
1376 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1377 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} //= do {
1378 my $version = $self->minimum_version;
1379 $version < KDBX_VERSION_4_0 ? STREAM_ID_SALSA20 : STREAM_ID_CHACHA20;
1380 };
1381 }
1382
1383 sub inner_random_stream_key {
1384 my $self = shift;
1385 if (@_) {
1386 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1387 # trick anyway.
1388 erase \$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
1389 erase \$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
1390 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1391 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} = shift;
1392 }
1393 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1394 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} //= random_bytes(64); # 32
1395 }
1396
1397 #########################################################################################
1398
1399 sub check {
1400 # - Fixer tool. Can repair inconsistencies, including:
1401 # - Orphaned binaries... not really a thing anymore since we now distribute binaries amongst entries
1402 # - Unused custom icons (OFF, data loss)
1403 # - Duplicate icons
1404 # - All data types are valid
1405 # - date times are correct
1406 # - boolean fields
1407 # - All UUIDs refer to things that exist
1408 # - previous parent group
1409 # - recycle bin
1410 # - last selected group
1411 # - last visible group
1412 # - Enforce history size limits (ON)
1413 # - Check headers/meta (ON)
1414 # - Duplicate deleted objects (ON)
1415 # - Duplicate window associations (OFF)
1416 # - Only one root group (ON)
1417 # - Header UUIDs match known ciphers/KDFs?
1418 }
1419
1420 #########################################################################################
1421
1422 sub _handle_signal {
1423 my $self = shift;
1424 my $object = shift;
1425 my $type = shift;
1426
1427 my %handlers = (
1428 'entry.uuid.changed' => \&_update_entry_uuid,
1429 'group.uuid.changed' => \&_update_group_uuid,
1430 );
1431 my $handler = $handlers{$type} or return;
1432 $self->$handler($object, @_);
1433 }
1434
1435 sub _update_group_uuid {
1436 my $self = shift;
1437 my $object = shift;
1438 my $new_uuid = shift;
1439 my $old_uuid = shift // return;
1440
1441 my $meta = $self->meta;
1442 $self->recycle_bin_uuid($new_uuid) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
1443 $self->entry_templates_group($new_uuid) if $old_uuid eq ($meta->{entry_templates_group} // '');
1444 $self->last_selected_group($new_uuid) if $old_uuid eq ($meta->{last_selected_group} // '');
1445 $self->last_top_visible_group($new_uuid) if $old_uuid eq ($meta->{last_top_visible_group} // '');
1446
1447 for my $group (@{$self->all_groups}) {
1448 $group->last_top_visible_entry($new_uuid) if $old_uuid eq ($group->{last_top_visible_entry} // '');
1449 $group->previous_parent_group($new_uuid) if $old_uuid eq ($group->{previous_parent_group} // '');
1450 }
1451 for my $entry (@{$self->all_entries}) {
1452 $entry->previous_parent_group($new_uuid) if $old_uuid eq ($entry->{previous_parent_group} // '');
1453 }
1454 }
1455
1456 sub _update_entry_uuid {
1457 my $self = shift;
1458 my $object = shift;
1459 my $new_uuid = shift;
1460 my $old_uuid = shift // return;
1461
1462 my $old_pretty = format_uuid($old_uuid);
1463 my $new_pretty = format_uuid($new_uuid);
1464 my $fieldref_match = qr/\{REF:([TUPANI])\@I:\Q$old_pretty\E\}/is;
1465
1466 for my $entry (@{$self->all_entries}) {
1467 $entry->previous_parent_group($new_uuid) if $old_uuid eq ($entry->{previous_parent_group} // '');
1468
1469 for my $string (values %{$entry->strings}) {
1470 next if !defined $string->{value} || $string->{value} !~ $fieldref_match;
1471 my $txn = $entry->begin_work;
1472 $string->{value} =~ s/$fieldref_match/{REF:$1\@I:$new_pretty}/g;
1473 $txn->commit;
1474 }
1475 }
1476 }
1477
1478 #########################################################################################
1479
1480 =attr comment
1481
1482 A text string associated with the database. Often unset.
1483
1484 =attr cipher_id
1485
1486 The UUID of a cipher used to encrypt the database when stored as a file.
1487
1488 See L</File::KDBX::Cipher>.
1489
1490 =attr compression_flags
1491
1492 Configuration for whether or not and how the database gets compressed. See
1493 L<File::KDBX::Constants/":compression">.
1494
1495 =attr master_seed
1496
1497 The master seed is a string of 32 random bytes that is used as salt in hashing the master key when loading
1498 and saving the database. If a challenge-response key is used in the master key, the master seed is also the
1499 challenge.
1500
1501 The master seed I<should> be changed each time the database is saved to file.
1502
1503 =attr transform_seed
1504
1505 The transform seed is a string of 32 random bytes that is used in the key derivation function, either as the
1506 salt or the key (depending on the algorithm).
1507
1508 The transform seed I<should> be changed each time the database is saved to file.
1509
1510 =attr transform_rounds
1511
1512 The number of rounds or iterations used in the key derivation function. Increasing this number makes loading
1513 and saving the database slower by design in order to make dictionary and brute force attacks more costly.
1514
1515 =attr encryption_iv
1516
1517 The initialization vector used by the cipher.
1518
1519 The encryption IV I<should> be changed each time the database is saved to file.
1520
1521 =attr inner_random_stream_key
1522
1523 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1524 within the database.
1525
1526 =attr stream_start_bytes
1527
1528 A string of 32 random bytes written in the header and encrypted in the body. If the bytes do not match when
1529 loading a file then the wrong master key was used or the file is corrupt. Only KDBX 2 and KDBX 3 files use
1530 this. KDBX 4 files use an improved HMAC method to verify the master key and data integrity of the header and
1531 entire file body.
1532
1533 =attr inner_random_stream_id
1534
1535 A number indicating the cipher algorithm used to encrypt the protected strings within the database, usually
1536 Salsa20 or ChaCha20. See L<File::KDBX::Constants/":random_stream">.
1537
1538 =attr kdf_parameters
1539
1540 A hash/dict of key-value pairs used to configure the key derivation function. This is the KDBX4+ way to
1541 configure the KDF, superceding L</transform_seed> and L</transform_rounds>.
1542
1543 =attr generator
1544
1545 The name of the software used to generate the KDBX file.
1546
1547 =attr header_hash
1548
1549 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1550
1551 =attr database_name
1552
1553 Name of the database.
1554
1555 =attr database_name_changed
1556
1557 Timestamp indicating when the database name was last changed.
1558
1559 =attr database_description
1560
1561 Description of the database
1562
1563 =attr database_description_changed
1564
1565 Timestamp indicating when the database description was last changed.
1566
1567 =attr default_username
1568
1569 When a new entry is created, the I<UserName> string will be populated with this value.
1570
1571 =attr default_username_changed
1572
1573 Timestamp indicating when the default username was last changed.
1574
1575 =attr maintenance_history_days
1576
1577 TODO... not really sure what this is. 😀
1578
1579 =attr color
1580
1581 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
1582 use this to help users visually distinguish between different databases.
1583
1584 =attr master_key_changed
1585
1586 Timestamp indicating when the master key was last changed.
1587
1588 =attr master_key_change_rec
1589
1590 Number of days until the agent should prompt to recommend changing the master key.
1591
1592 =attr master_key_change_force
1593
1594 Number of days until the agent should prompt to force changing the master key.
1595
1596 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
1597 C<File::KDBX> does NOT enforce it.
1598
1599 =attr recycle_bin_enabled
1600
1601 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1602
1603 =attr recycle_bin_uuid
1604
1605 The UUID of a group used to store thrown-away groups and entries.
1606
1607 =attr recycle_bin_changed
1608
1609 Timestamp indicating when the recycle bin was last changed.
1610
1611 =attr entry_templates_group
1612
1613 The UUID of a group containing template entries used when creating new entries.
1614
1615 =attr entry_templates_group_changed
1616
1617 Timestamp indicating when the entry templates group was last changed.
1618
1619 =attr last_selected_group
1620
1621 The UUID of the previously-selected group.
1622
1623 =attr last_top_visible_group
1624
1625 The UUID of the group visible at the top of the list.
1626
1627 =attr history_max_items
1628
1629 The maximum number of historical entries allowed to be saved for each entry.
1630
1631 =attr history_max_size
1632
1633 The maximum total size (in bytes) that each individual entry's history is allowed to grow.
1634
1635 =attr settings_changed
1636
1637 Timestamp indicating when the database settings were last updated.
1638
1639 =attr protect_title
1640
1641 Alias of the L</memory_protection> setting for the I<Title> string.
1642
1643 =attr protect_username
1644
1645 Alias of the L</memory_protection> setting for the I<UserName> string.
1646
1647 =attr protect_password
1648
1649 Alias of the L</memory_protection> setting for the I<Password> string.
1650
1651 =attr protect_url
1652
1653 Alias of the L</memory_protection> setting for the I<URL> string.
1654
1655 =attr protect_notes
1656
1657 Alias of the L</memory_protection> setting for the I<Notes> string.
1658
1659 =cut
1660
1661 #########################################################################################
1662
1663 sub TO_JSON { +{%{$_[0]}} }
1664
1665 1;
1666 __END__
1667
1668 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
1669
1670 =head1 SYNOPSIS
1671
1672 use File::KDBX;
1673
1674 my $kdbx = File::KDBX->new;
1675
1676 my $group = $kdbx->add_group(
1677 name => 'Passwords',
1678 );
1679
1680 my $entry = $group->add_entry(
1681 title => 'My Bank',
1682 password => 's3cr3t',
1683 );
1684
1685 $kdbx->dump_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1686
1687 $kdbx = File::KDBX->load_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1688
1689 for my $entry (@{ $kdbx->all_entries }) {
1690 say 'Entry: ', $entry->title;
1691 }
1692
1693 =head1 DESCRIPTION
1694
1695 B<File::KDBX> provides everything you need to work with a KDBX database. A KDBX database is a hierarchical
1696 object database which is commonly used to store secret information securely. It was developed for the KeePass
1697 password safe. See L</"KDBX Introduction"> for more information about KDBX.
1698
1699 This module lets you query entries, create new entries, delete entries and modify entries. The distribution
1700 also includes various parsers and generators for serializing and persisting databases.
1701
1702 This design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
1703 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
1704 that works well in most cases but has a small backlog of bugs and security issues and also does not work with
1705 newer KDBX version 4 files. If you're coming here from the B<File::KeePass> world, you might be interested in
1706 L<File::KeePass::KDBX> that is a drop-in replacement for B<File::KeePass> that uses B<File::KDBX> for storage.
1707
1708 =head2 KDBX Introduction
1709
1710 A KDBX database consists of a hierarchical I<group> of I<entries>. Entries can contain zero or more key-value
1711 pairs of I<strings> and zero or more I<binaries> (i.e. octet strings). Groups, entries, strings and binaries:
1712 that's the KDBX vernacular. A small amount of metadata (timestamps, etc.) is associated with each entry, group
1713 and the database as a whole.
1714
1715 You can think of a KDBX database kind of like a file system, where groups are directories, entries are files,
1716 and strings and binaries make up a file's contents.
1717
1718 Databases are typically persisted as a encrypted, compressed files. They are usually accessed directly (i.e.
1719 not over a network). The primary focus of this type of database is data security. It is ideal for storing
1720 relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as
1721 have the correct I<master key>. Even if the database file were to be "leaked" to the public Internet, it
1722 should be virtually impossible to crack with a strong key. See L</SECURITY> for an overview of security
1723 considerations.
1724
1725 =head1 RECIPES
1726
1727 =head2 Create a new database
1728
1729 my $kdbx = File::KDBX->new;
1730
1731 my $group = $kdbx->add_group(name => 'Passwords);
1732 my $entry = $group->add_entry(
1733 title => 'WayneCorp',
1734 username => 'bwayne',
1735 password => 'iambatman',
1736 url => 'https://example.com/login'
1737 );
1738 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
1739
1740 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
1741
1742 =head2 Read an existing database
1743
1744 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
1745 $kdbx->unlock;
1746
1747 for my $entry (@{ $kdbx->all_entries }) {
1748 say 'Found password for ', $entry->title, ':';
1749 say ' Username: ', $entry->username;
1750 say ' Password: ', $entry->password;
1751 }
1752
1753 =head2 Search for entries
1754
1755 my @entries = $kdbx->find_entries({
1756 title => 'WayneCorp',
1757 }, search => 1);
1758
1759 See L</QUERY> for many more query examples.
1760
1761 =head2 Search for entries by auto-type window association
1762
1763 my @entry_key_sequences = $kdbx->find_entries_for_window('WayneCorp - Mozilla Firefox');
1764 for my $pair (@entry_key_sequences) {
1765 my ($entry, $key_sequence) = @$pair;
1766 say 'Entry title: ', $entry->title, ', key sequence: ', $key_sequence;
1767 }
1768
1769 Example output:
1770
1771 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
1772
1773 =head1 SECURITY
1774
1775 One of the biggest threats to your database security is how easily the encryption key can be brute-forced.
1776 Strong brute-force protection depends on a couple factors:
1777
1778 =for :list
1779 * Using unguessable passwords, passphrases and key files.
1780 * Using a brute-force resistent key derivation function.
1781
1782 The first factor is up to you. This module does not enforce strong master keys. It is up to you to pick or
1783 generate strong keys.
1784
1785 The KDBX format allows for the key derivation function to be tuned. The idea is that you want each single
1786 brute-foce attempt to be expensive (in terms of time, CPU usage or memory usage), so that making a lot of
1787 attempts (which would be required if you have a strong master key) gets I<really> expensive.
1788
1789 How expensive you want to make each attempt is up to you and can depend on the application.
1790
1791 This and other KDBX-related security issues are covered here more in depth:
1792 L<https://keepass.info/help/base/security.html>
1793
1794 Here are other security risks you should be thinking about:
1795
1796 =head2 Cryptography
1797
1798 This distribution uses the excellent L<CryptX> and L<Crypt::Argon2> packages to handle all crypto-related
1799 functions. As such, a lot of the security depends on the quality of these dependencies. Fortunately these
1800 modules are maintained and appear to have good track records.
1801
1802 The KDBX format has evolved over time to incorporate improved security practices and cryptographic functions.
1803 This package uses the following functions for authentication, hashing, encryption and random number
1804 generation:
1805
1806 =for :list
1807 * AES-128 (legacy)
1808 * AES-256
1809 * Argon2d & Argon2id
1810 * CBC block mode
1811 * HMAC-SHA256
1812 * SHA256
1813 * SHA512
1814 * Salsa20 & ChaCha20
1815 * Twofish
1816
1817 At the time of this writing, I am not aware of any successful attacks against any of these functions. These
1818 are among the most-analyzed and widely-adopted crypto functions available.
1819
1820 The KDBX format allows the body cipher and key derivation function to be configured. If a flaw is discovered
1821 in one of these functions, you can hopefully just switch to a better function without needing to update this
1822 software. A later software release may phase out the use of any functions which are no longer secure.
1823
1824 =head2 Memory Protection
1825
1826 It is not a good idea to keep secret information unencrypted in system memory for longer than is needed. The
1827 address space of your program can generally be read by a user with elevated privileges on the system. If your
1828 system is memory-constrained or goes into a hibernation mode, the contents of your address space could be
1829 written to a disk where it might be persisted for long time.
1830
1831 There might be system-level things you can do to reduce your risk, like using swap encryption and limiting
1832 system access to your program's address space while your program is running.
1833
1834 B<File::KDBX> helps minimize (but not eliminate) risk by keeping secrets encrypted in memory until accessed
1835 and zeroing out memory that holds secrets after they're no longer needed, but it's not a silver bullet.
1836
1837 For one thing, the encryption key is stored in the same address space. If core is dumped, the encryption key
1838 is available to be found out. But at least there is the chance that the encryption key and the encrypted
1839 secrets won't both be paged out while memory-constrained.
1840
1841 Another problem is that some perls (somewhat notoriously) copy around memory behind the scenes willy nilly,
1842 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
1843 be impossible. The good news is that perls with SvPV copy-on-write (enabled by default beginning with perl
1844 5.20) are much better in this regard. With COW, it's mostly possible to know what operations will cause perl
1845 to copy the memory of a scalar string, and the number of copies will be significantly reduced. There is a unit
1846 test named F<t/memory-protection.t> in this distribution that can be run on POSIX systems to determine how
1847 well B<File::KDBX> memory protection is working.
1848
1849 Memory protection also depends on how your application handles secrets. If your app code is handling scalar
1850 strings with secret information, it's up to you to make sure its memory is zeroed out when no longer needed.
1851 L<File::KDBX::Util/erase> et al. provide some tools to help accomplish this. Or if you're not too concerned
1852 about the risks memory protection is meant to mitigate, then maybe don't worry about it. The security policy
1853 of B<File::KDBX> is to try hard to keep secrets protected while in memory so that your app might claim a high
1854 level of security, in case you care about that.
1855
1856 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
1857
1858 Many systems allow programs to mark unswappable pages. Secret information should ideally be stored in such
1859 pages. You could potentially use L<mlockall(2)> (or equivalent for your system) in your own application to
1860 prevent the entire address space from being swapped.
1861
1862 Some systems provide special syscalls for storing secrets in memory while keeping the encryption key outside
1863 of the program's address space, like C<CryptProtectMemory> for Windows. This could be a good option, though
1864 unfortunately not portable.
1865
1866 =head1 QUERY
1867
1868 Several methods take a I<query> as an argument (e.g. L</find_entries>). A query is just a subroutine that you
1869 can either write yourself or have generated for you based on either a simple expression or a declarative
1870 structure. It's easier to have your query generated, so I'll cover that first.
1871
1872 =head2 Simple Expression
1873
1874 A simple expression is mostly compatible with the KeePass 2 implementation
1875 L<described here|https://keepass.info/help/base/search.html#mode_se>.
1876
1877 An expression is a string with one or more space-separated terms. Terms with spaces can be enclosed in double
1878 quotes. Terms are negated if they are prefixed with a minus sign. A record must match every term on at least
1879 one of the given fields.
1880
1881 So a simple expression is something like what you might type into a search engine. You can generate a simple
1882 expression query using L<File::KDBX::Util/simple_expression_query> or by passing the simple expression as
1883 a B<string reference> to search methods like L</find_entries>.
1884
1885 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
1886
1887 my @entries = $kdbx->find_entries([ \'canyon', qw(title) ]);
1888
1889 Notice the first argument is a B<stringref>. This diambiguates a simple expression from other types of queries
1890 covered below.
1891
1892 As mentioned, a simple expression can have multiple terms. This simple expression query matches any entry that
1893 has the words "red" B<and> "canyon" anywhere in the title:
1894
1895 my @entries = $kdbx->find_entries([ \'red canyon', qw(title) ]);
1896
1897 Each term in the simple expression must be found for an entry to match.
1898
1899 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
1900
1901 my @entries = $kdbx->find_entries([ \'red -canyon', qw(title) ]);
1902
1903 To search over multiple fields simultaneously, just list them. To search for entries with "grocery" in the
1904 title or notes but not "Foodland":
1905
1906 my @entries = $kdbx->find_entries([ \'grocery -Foodland', qw(title notes) ]);
1907
1908 The default operator is a case-insensitive regexp match, which is fine for searching text loosely. You can use
1909 just about any binary comparison operator that perl supports. To specify an operator, list it after the simple
1910 expression. For example, to search for any entry that has been used at least five times:
1911
1912 my @entries = $kdbx->find_entries([ \5, '>=', qw(usage_count) ]);
1913
1914 It helps to read it right-to-left, like "usage_count is >= 5".
1915
1916 If you find the disambiguating structures to be confusing, you can also the L</find_entries_simple> method as
1917 a more intuitive alternative. The following example is equivalent to the previous:
1918
1919 my @entries = $kdbx->find_entries_simple(5, '>=', qw(usage_count));
1920
1921 =head2 Declarative Query
1922
1923 Structuring a declarative query is similar to L<SQL::Abstract/"WHERE CLAUSES">, but you don't have to be
1924 familiar with that module. Just learn by examples.
1925
1926 To search for all entries in a database titled "My Bank":
1927
1928 my @entries = $kdbx->find_entries({ title => 'My Bank' });
1929
1930 The query here is C<< { title => 'My Bank' } >>. A hashref can contain key-value pairs where the key is
1931 a attribute of the thing being searched for (in this case an entry) and the value is what you want the thing's
1932 attribute to be to consider it a match. In this case, the attribute we're using as our match criteria is
1933 L<File::KDBX::Entry/title>, a text field. If an entry has its title attribute equal to "My Bank", it's
1934 a match.
1935
1936 A hashref can contain multiple attributes. The search candidate will be a match if I<all> of the specified
1937 attributes are equal to their respective values. For example, to search for all entries with a particular URL
1938 B<AND> username:
1939
1940 my @entries = $kdbx->find_entries({
1941 url => 'https://example.com',
1942 username => 'neo',
1943 });
1944
1945 To search for entries matching I<any> criteria, just change the hashref to an arrayref. To search for entries
1946 with a particular URL B<OR> a particular username:
1947
1948 my @entries = $kdbx->find_entries([ # <-- square bracket
1949 url => 'https://example.com',
1950 username => 'neo',
1951 ]);
1952
1953 You can user different operators to test different types of attributes. The L<File::KDBX::Entry/icon_id>
1954 attribute is a number, so we should use a number comparison operator. To find entries using the smartphone
1955 icon:
1956
1957 my @entries = $kdbx->find_entries({
1958 icon_id => { '==', ICON_SMARTPHONE },
1959 });
1960
1961 Note: L<File::KDBX::Constants/ICON_SMARTPHONE> is just a constant from L<File::KDBX::Constants>. It isn't
1962 special to this example or to queries generally. We could have just used a literal number.
1963
1964 The important thing to notice here is how we wrapped the condition in another arrayref with a single key-pair
1965 where the key is the name of an operator and the value is the thing to match against. The supported operators
1966 are:
1967
1968 =for :list
1969 * C<eq> - String equal
1970 * C<ne> - String not equal
1971 * C<lt> - String less than
1972 * C<gt> - String greater than
1973 * C<le> - String less than or equal
1974 * C<ge> - String greater than or equal
1975 * C<==> - Number equal
1976 * C<!=> - Number not equal
1977 * C<< < >> - Number less than
1978 * C<< > >>> - Number greater than
1979 * C<< <= >> - Number less than or equal
1980 * C<< >= >> - Number less than or equal
1981 * C<=~> - String match regular expression
1982 * C<!~> - String does not match regular expression
1983 * C<!> - Boolean false
1984 * C<!!> - Boolean true
1985
1986 Other special operators:
1987
1988 =for :list
1989 * C<-true> - Boolean true
1990 * C<-false> - Boolean false
1991 * C<-not> - Boolean false (alias for C<-false>)
1992 * C<-defined> - Is defined
1993 * C<-undef> - Is not d efined
1994 * C<-empty> - Is empty
1995 * C<-nonempty> - Is not empty
1996 * C<-or> - Logical or
1997 * C<-and> - Logical and
1998
1999 Let's see another example using an explicit operator. To find all groups except one in particular (identified
2000 by its L<File::KDBX::Group/uuid>), we can use the C<ne> (string not equal) operator:
2001
2002 my ($group, @other) = $kdbx->find_groups({
2003 uuid => {
2004 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
2005 },
2006 });
2007 if (@other) { say "Problem: there can be only one!" }
2008
2009 Note: L<File::KDBX::Util/uuid> is a little helper function to convert a UUID in its pretty form into octets.
2010 This helper function isn't special to this example or to queries generally. It could have been written with
2011 a literal such as C<"\x59\x6f\x75\x20\x61...">, but that's harder to read.
2012
2013 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2014
2015 Testing the truthiness of an attribute is a little bit different because it isn't a binary operation. To find
2016 all entries with the password quality check disabled:
2017
2018 my @entries = $kdbx->find_entries({ '!' => 'quality_check' });
2019
2020 This time the string after the operator is the attribute name rather than a value to compare the attribute
2021 against. To test that a boolean value is true, use the C<!!> operator (or C<-true> if C<!!> seems a little too
2022 weird for your taste):
2023
2024 my @entries = $kdbx->find_entries({ '!!' => 'quality_check' });
2025 my @entries = $kdbx->find_entries({ -true => 'quality_check' });
2026
2027 Yes, there is also a C<-false> and a C<-not> if you prefer one of those over C<!>. C<-false> and C<-not>
2028 (along with C<-true>) are also special in that you can use them to invert the logic of a subquery. These are
2029 logically equivalent:
2030
2031 my @entries = $kdbx->find_entries([ -not => { title => 'My Bank' } ]);
2032 my @entries = $kdbx->find_entries({ title => { 'ne' => 'My Bank' } });
2033
2034 These special operators become more useful when combined with two more special operators: C<-and> and C<-or>.
2035 With these, it is possible to construct more interesting queries with groups of logic. For example:
2036
2037 my @entries = $kdbx->find_entries({
2038 title => { '=~', qr/bank/ },
2039 -not => {
2040 -or => {
2041 notes => { '=~', qr/business/ },
2042 icon_id => { '==', ICON_TRASHCAN_FULL },
2043 },
2044 },
2045 });
2046
2047 In English, find entries where the word "bank" appears anywhere in the title but also do not have either the
2048 word "business" in the notes or is using the full trashcan icon.
2049
2050 =head2 Subroutine Query
2051
2052 Lastly, as mentioned at the top, you can ignore all this and write your own subroutine. Your subroutine will
2053 be called once for each thing being searched over. The single argument is the search candidate. The subroutine
2054 should match the candidate against whatever criteria you want and return true if it matches. The C<find_*>
2055 methods collect all matching things and return them.
2056
2057 For example, to find all entries in the database titled "My Bank":
2058
2059 my @entries = $kdbx->find_entries(sub { shift->title eq 'My Bank' });
2060 # logically the same as this declarative structure:
2061 my @entries = $kdbx->find_entries({ title => 'My Bank' });
2062 # as well as this simple expression:
2063 my @entries = $kdbx->find_entries([ \'My Bank', 'eq', qw{title} ]);
2064
2065 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2066
2067 All of these query mechanisms described in this section are just tools, each with its own set of limitations.
2068 If the tools are getting in your way, you can of course iterate over the contents of a database and implement
2069 your own query logic, like this:
2070
2071 for my $entry (@{ $kdbx->all_entries }) {
2072 if (wanted($entry)) {
2073 do_something($entry);
2074 }
2075 else {
2076 ...
2077 }
2078 }
2079
2080 =head1 ERRORS
2081
2082 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
2083 mechanisms. Fatal errors are propagated using L<functions/die> and non-fatal errors (a.k.a. warnings) are
2084 propagated using L<functions/warn> while adhering to perl's L<warnings> system. If you're already familiar
2085 with these mechanisms, you can skip this section.
2086
2087 You can catch fatal errors using L<functions/eval> (or something like L<Try::Tiny>) and non-fatal errors using
2088 C<$SIG{__WARN__}> (see L<variables/%SIG>). Examples:
2089
2090 use File::KDBX::Error qw(error);
2091
2092 my $key = ''; # uh oh
2093 eval {
2094 $kdbx->load_file('whatever.kdbx', $key);
2095 };
2096 if (my $error = error($@)) {
2097 handle_missing_key($error) if $error->type eq 'key.missing';
2098 $error->throw;
2099 }
2100
2101 or using C<Try::Tiny>:
2102
2103 try {
2104 $kdbx->load_file('whatever.kdbx', $key);
2105 }
2106 catch {
2107 handle_error($_);
2108 };
2109
2110 Catching non-fatal errors:
2111
2112 my @warnings;
2113 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2114
2115 $kdbx->load_file('whatever.kdbx', $key);
2116
2117 handle_warnings(@warnings) if @warnings;
2118
2119 By default perl prints warnings to C<STDERR> if you don't catch them. If you don't want to catch them and also
2120 don't want them printed to C<STDERR>, you can suppress them lexically (perl v5.28 or higher required):
2121
2122 {
2123 no warnings 'File::KDBX';
2124 ...
2125 }
2126
2127 or locally:
2128
2129 {
2130 local $File::KDBX::WARNINGS = 0;
2131 ...
2132 }
2133
2134 or globally in your program:
2135
2136 $File::KDBX::WARNINGS = 0;
2137
2138 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2139
2140 =head1 ENVIRONMENT
2141
2142 This software will alter its behavior depending on the value of certain environment variables:
2143
2144 =for :list
2145 * C<PERL_FILE_KDBX_XS> - Do not use L<File::KDBX::XS> if false (default: true)
2146 * C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
2147 * C<NO_FORK> - Do not fork if true (default: false)
2148
2149 =head1 CAVEATS
2150
2151 Some features (e.g. parsing) require 64-bit perl. It should be possible and actually pretty easy to make it
2152 work using L<Math::BigInt>, but I need to build a 32-bit perl in order to test it and frankly I'm still
2153 figuring out how. I'm sure it's simple so I'll mark this one "TODO", but for now an exception will be thrown
2154 when trying to use such features with undersized IVs.
2155
2156 =head1 SEE ALSO
2157
2158 L<File::KeePass> is a much older alternative. It's good but has a backlog of bugs and lacks support for newer
2159 KDBX features.
2160
2161 =attr sig1
2162
2163 =attr sig2
2164
2165 =attr version
2166
2167 =attr headers
2168
2169 =attr inner_headers
2170
2171 =attr meta
2172
2173 =attr binaries
2174
2175 =attr deleted_objects
2176
2177 =attr raw
2178
2179 $value = $kdbx->$attr;
2180 $kdbx->$attr($value);
2181
2182 Get and set attributes.
2183
2184 =cut
This page took 0.181898 seconds and 4 git commands to generate.