File-KDBX

 view release on metacpan or  search on metacpan

lib/File/KDBX/Loader/KDB.pm  view on Meta::CPAN

package File::KDBX::Loader::KDB;
# ABSTRACT: Read KDB files

use warnings;
use strict;

use Encode qw(encode);
use File::KDBX::Constants qw(:header :cipher :random_stream :icon);
use File::KDBX::Error;
use File::KDBX::Util qw(:class :empty :io :uuid load_optional);
use File::KDBX;
use Ref::Util qw(is_arrayref is_hashref);
use Scalar::Util qw(looks_like_number);
use Time::Piece 1.33;
use boolean;
use namespace::clean;

extends 'File::KDBX::Loader';

our $VERSION = '0.906'; # VERSION

my $DEFAULT_EXPIRATION = Time::Piece->strptime('2999-12-31 23:59:59', '%Y-%m-%d %H:%M:%S');

sub _read_headers { '' }

sub _read_body {
    my $self = shift;
    my $fh = shift;
    my $key = shift;
    my $buf = shift;

    load_optional('File::KeePass');

    $buf .= do { local $/; <$fh> };

    $key = $self->kdbx->composite_key($key, keep_primitive => 1);

    my $k = eval { File::KeePass->new->parse_db(\$buf, _convert_kdbx_to_keepass_master_key($key)) };
    if (my $err = $@) {
        throw 'Failed to parse KDB file', error => $err;
    }

    $k->unlock;
    $self->kdbx->key($key);

    return convert_keepass_to_kdbx($k, $self->kdbx);
}

# This is also used by File::KDBX::Dumper::KDB.
sub _convert_kdbx_to_keepass_master_key {
    my $key = shift;

    my @keys = @{$key->keys};
    if (@keys == 1 && !$keys[0]->can('filepath')) {
        return [encode('CP-1252', $keys[0]->{primitive})];     # just a password
    }
    elsif (@keys == 1) {
        return [undef, \$keys[0]->raw_key]; # just a keyfile
    }
    elsif (@keys == 2 && !$keys[0]->can('filepath') && $keys[1]->can('filepath')) {
        return [encode('CP-1252', $keys[0]->{primitive}), \$keys[1]->raw_key];
    }
    throw 'Cannot use this key to load a KDB file', key => $key;
}


sub convert_keepass_to_kdbx {
    my $k    = shift;
    my $kdbx = shift // File::KDBX->new;

    $kdbx->{headers} //= {};
    _convert_keepass_to_kdbx_headers($k->{header}, $kdbx);



( run in 1.287 second using v1.01-cache-2.11-cpan-39bf76dae61 )