|
@@ -2,7 +2,8 @@ import getpass
|
|
|
import os.path
|
|
|
import re
|
|
|
import tempfile
|
|
|
-from binascii import hexlify, unhexlify
|
|
|
+from binascii import hexlify, unhexlify, a2b_base64
|
|
|
+from unittest.mock import MagicMock
|
|
|
|
|
|
import pytest
|
|
|
|
|
@@ -11,7 +12,7 @@ from ..crypto.key import PlaintextKey, AuthenticatedKey, RepoKey, KeyfileKey, \
|
|
|
Blake2KeyfileKey, Blake2RepoKey, Blake2AuthenticatedKey, \
|
|
|
AESOCBKeyfileKey, AESOCBRepoKey, CHPOKeyfileKey, CHPORepoKey
|
|
|
from ..crypto.key import ID_HMAC_SHA_256, ID_BLAKE2b_256
|
|
|
-from ..crypto.key import TAMRequiredError, TAMInvalid, TAMUnsupportedSuiteError, UnsupportedManifestError
|
|
|
+from ..crypto.key import TAMRequiredError, TAMInvalid, TAMUnsupportedSuiteError, UnsupportedManifestError, UnsupportedKeyFormatError
|
|
|
from ..crypto.key import identify_key
|
|
|
from ..crypto.low_level import bytes_to_long
|
|
|
from ..crypto.low_level import IntegrityError as IntegrityErrorBase
|
|
@@ -20,6 +21,7 @@ from ..helpers import Location
|
|
|
from ..helpers import StableDict
|
|
|
from ..helpers import get_security_dir
|
|
|
from ..helpers import msgpack
|
|
|
+from ..constants import KEY_ALGORITHMS
|
|
|
|
|
|
|
|
|
class TestKey:
|
|
@@ -379,3 +381,44 @@ class TestTAM:
|
|
|
|
|
|
with pytest.raises(TAMInvalid):
|
|
|
key.unpack_and_verify_manifest(blob)
|
|
|
+
|
|
|
+
|
|
|
+def test_decrypt_key_file_unsupported_algorithm():
|
|
|
+ """We will add more algorithms in the future. We should raise a helpful error."""
|
|
|
+ key = KeyfileKey(None)
|
|
|
+ encrypted = msgpack.packb({
|
|
|
+ 'algorithm': 'THIS ALGORITHM IS NOT SUPPORTED',
|
|
|
+ 'version': 1,
|
|
|
+ })
|
|
|
+
|
|
|
+ with pytest.raises(UnsupportedKeyFormatError):
|
|
|
+ key.decrypt_key_file(encrypted, "hello, pass phrase")
|
|
|
+
|
|
|
+
|
|
|
+def test_decrypt_key_file_v2_is_unsupported():
|
|
|
+ """There may eventually be a version 2 of the format. For now we should raise a helpful error."""
|
|
|
+ key = KeyfileKey(None)
|
|
|
+ encrypted = msgpack.packb({
|
|
|
+ 'version': 2,
|
|
|
+ })
|
|
|
+
|
|
|
+ with pytest.raises(UnsupportedKeyFormatError):
|
|
|
+ key.decrypt_key_file(encrypted, "hello, pass phrase")
|
|
|
+
|
|
|
+
|
|
|
+@pytest.mark.parametrize('cli_argument, expected_algorithm', KEY_ALGORITHMS.items())
|
|
|
+def test_key_file_roundtrip(monkeypatch, cli_argument, expected_algorithm):
|
|
|
+ def to_dict(key):
|
|
|
+ extract = 'repository_id', 'enc_key', 'enc_hmac_key', 'id_key', 'chunk_seed'
|
|
|
+ return {a: getattr(key, a) for a in extract}
|
|
|
+
|
|
|
+ repository = MagicMock(id=b'repository_id')
|
|
|
+ monkeypatch.setenv('BORG_PASSPHRASE', "hello, pass phrase")
|
|
|
+
|
|
|
+ save_me = RepoKey.create(repository, args=MagicMock(key_algorithm=cli_argument))
|
|
|
+ saved = repository.save_key.call_args.args[0]
|
|
|
+ repository.load_key.return_value = saved
|
|
|
+ load_me = RepoKey.detect(repository, manifest_data=None)
|
|
|
+
|
|
|
+ assert to_dict(load_me) == to_dict(save_me)
|
|
|
+ assert msgpack.unpackb(a2b_base64(saved))[b'algorithm'] == expected_algorithm.encode()
|