X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fp5-File-KDBX;a=blobdiff_plain;f=t%2Fkeys.t;h=62d2a1a35ab5be2f196427113345ff142831133d;hp=0d03e6536f83e32d64e021790d0144cf8b59ff94;hb=1b913e5c8826cae2355b0076ec5701aa3ce63c63;hpb=b30990a507ef30b6f5b6fcb799a2759632c77ff0 diff --git a/t/keys.t b/t/keys.t index 0d03e65..62d2a1a 100644 --- a/t/keys.t +++ b/t/keys.t @@ -7,10 +7,11 @@ use lib 't/lib'; use TestCommon; use Crypt::Misc 0.029 qw(decode_b64 encode_b64); +use File::KDBX::Constants qw(:key_file); +use File::KDBX::Key; +use File::Temp qw(tempfile); use Test::More; -BEGIN { use_ok 'File::KDBX::Key' } - subtest 'Primitives' => sub { my $pkey = File::KDBX::Key->new('password'); isa_ok $pkey, 'File::KDBX::Key::Password'; @@ -33,52 +34,90 @@ subtest 'Primitives' => sub { 'Can calculate raw key from composite' or diag encode_b64($ckey->raw_key); }; -subtest 'File keys' => sub { - my $key = File::KDBX::Key::File->new(testfile(qw{keys xmlv1.key})); - is $key->raw_key, decode_b64('OF9tj+tfww1kHNWQaJlZWIlBdoTVXOazP8g/vZK7NcI='), - 'Can calculate raw key from XML file' or diag encode_b64($key->raw_key); - is $key->type, 'xml', 'file type is detected as xml'; - is $key->version, '1.0', 'file version is detected as xml'; - - $key = File::KDBX::Key::File->new(testfile(qw{keys xmlv2.key})); - is $key->raw_key, decode_b64('OF9tj+tfww1kHNWQaJlZWIlBdoTVXOazP8g/vZK7NcI='), - 'Can calculate raw key from XML file' or diag encode_b64($key->raw_key); - is $key->type, 'xml', 'file type is detected as xml'; - is $key->version, '2.0', 'file version is detected as xml'; - - $key = File::KDBX::Key::File->new(testfile(qw{keys binary.key})); - is $key->raw_key, decode_b64('QlkDxuYbDPDpDXdK1470EwVBL+AJBH2gvPA9lxNkFEk='), - 'Can calculate raw key from binary file' or diag encode_b64($key->raw_key); - is $key->type, 'binary', 'file type is detected as binary'; - - $key = File::KDBX::Key::File->new(testfile(qw{keys hex.key})); - is $key->raw_key, decode_b64('QlkDxuYbDPDpDXdK1470EwVBL+AJBH2gvPA9lxNkFEk='), - 'Can calculate raw key from hex file' or diag encode_b64($key->raw_key); - is $key->type, 'hex', 'file type is detected as hex'; - - $key = File::KDBX::Key::File->new(testfile(qw{keys hashed.key})); - is $key->raw_key, decode_b64('8vAO4mrMeq6iCa1FHeWm/Mj5al8HIv2ajqsqsSeUC6U='), - 'Can calculate raw key from binary file' or diag encode_b64($key->raw_key); - is $key->type, 'hashed', 'file type is detected as hashed'; - +for my $test ( + [KEY_FILE_TYPE_XML, 'xmlv1.key', 'OF9tj+tfww1kHNWQaJlZWIlBdoTVXOazP8g/vZK7NcI=', '1.0'], + [KEY_FILE_TYPE_XML, 'xmlv2.key', 'OF9tj+tfww1kHNWQaJlZWIlBdoTVXOazP8g/vZK7NcI=', '2.0'], + [KEY_FILE_TYPE_BINARY, 'binary.key', 'QlkDxuYbDPDpDXdK1470EwVBL+AJBH2gvPA9lxNkFEk='], + [KEY_FILE_TYPE_HEX, 'hex.key', 'QlkDxuYbDPDpDXdK1470EwVBL+AJBH2gvPA9lxNkFEk='], + [KEY_FILE_TYPE_HASHED, 'hashed.key', '8vAO4mrMeq6iCa1FHeWm/Mj5al8HIv2ajqsqsSeUC6U='], +) { + my ($type) = @$test; + subtest "Load $type key file" => sub { + my ($type, $filename, $expected_key, $version) = @_; + + my $key = File::KDBX::Key::File->new(testfile('keys', $filename)); + is $key->raw_key, decode_b64($expected_key), + "Can calculate raw key from $type file" or diag encode_b64($key->raw_key); + is $key->type, $type, "File type is detected as $type"; + is $key->version, $version, "File version is detected as $version" if defined $version; + }, @$test; + + subtest "Save $type key file" => sub { + my ($type, $filename, $expected_key, $version) = @_; + + my ($fh, $filepath) = tempfile('keyfile-XXXXXX', TMPDIR => 1, UNLINK => 1, SUFFIX => '.key'); + note $filepath; + my $key = File::KDBX::Key::File->new( + filepath => $filepath, + type => $type, + version => $version, + raw_key => decode_b64($expected_key), + ); + + my $e = exception { $key->save }; + close($fh); + + if ($type == KEY_FILE_TYPE_HASHED) { + like $e, qr/invalid type/i, "Cannot save $type file"; + return; + } + is $e, undef, "Save $type file"; + + my $key2 = File::KDBX::Key::File->new($filepath); + is $key2->type, $key->type, 'Loaded key file has the same type'; + is $key2->raw_key, $key->raw_key, 'Loaded key file has the same raw key'; + }, @$test; +} + +subtest 'IO handle key files' => sub { my $buf = 'password'; open(my $fh, '<', \$buf) or die "open failed: $!\n"; - $key = File::KDBX::Key::File->new($fh); + my $key = File::KDBX::Key::File->new($fh); is $key->raw_key, decode_b64('XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg='), 'Can calculate raw key from file handle' or diag encode_b64($key->raw_key); is $key->type, 'hashed', 'file type is detected as hashed'; - is exception { File::KDBX::Key::File->new }, undef, 'Can instantiate uninitialized'; + my ($fh_save, $filepath) = tempfile('keyfile-XXXXXX', TMPDIR => 1, UNLINK => 1, SUFFIX => '.key'); + ok $key->save(fh => $fh_save, type => KEY_FILE_TYPE_XML), 'Save key file using IO handle'; + close($fh_save); + + my $key2 = File::KDBX::Key::File->new($filepath); + is $key2->type, KEY_FILE_TYPE_XML, 'Loaded key file has the same type'; + is $key2->filepath, $filepath, 'Loaded key remembers the filepath'; + is $key2->raw_key, $key->raw_key, 'Loaded key file has the same raw key'; + $key2->reload; + is $key2->raw_key, $key->raw_key, 'Raw key is the same when reloaded same file'; + + my $easy_raw_key = "\1" x 32; + $key->init(\$easy_raw_key); + $key->save(filepath => $filepath); + + $key2->reload; + is $key2->raw_key, "\1" x 32, 'Raw key is changed after reload'; +}; + +subtest 'Key file error handling' => sub { + is exception { File::KDBX::Key::File->new }, undef, 'Cannot instantiate uninitialized'; like exception { File::KDBX::Key::File->init }, - qr/^Missing key primitive/, 'Throws if no primitive is provided'; + qr/^Missing key primitive/, 'Throw if no primitive is provided'; like exception { File::KDBX::Key::File->new(testfile(qw{keys nonexistent})) }, - qr/^Failed to open key file/, 'Throws if file is missing'; + qr/^Failed to open key file/, 'Throw if file is missing'; like exception { File::KDBX::Key::File->new({}) }, - qr/^Unexpected primitive type/, 'Throws if primitive is the wrong type'; + qr/^Unexpected primitive type/, 'Throw if primitive is the wrong type'; }; done_testing;