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