]> Dogcows Code - chaz/p5-File-KDBX/blobdiff - t/keys.t
Add key file saving and refactor some stuff
[chaz/p5-File-KDBX] / t / keys.t
index 0d03e6536f83e32d64e021790d0144cf8b59ff94..62d2a1a35ab5be2f196427113345ff142831133d 100644 (file)
--- 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;
This page took 0.020079 seconds and 4 git commands to generate.