From 3239836dce716bcab0ebab7a0137bdee58d00203 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 3 May 2022 21:25:44 +0200 Subject: [PATCH 1/2] fix key id hash compat check: also support new->new the check only considered old key -> new key changes, but new key to new key is of course also fine. e.g. repokey-aes-ocb -> repokey-aes-ocb (both use hmac-sha256 as id hash) --- src/borg/crypto/key.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index ed4c375d2..e74847440 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -596,18 +596,16 @@ def create(cls, repository, args, *, other_key=None): # user must use an AEADKeyBase subclass (AEAD modes with session keys) raise Error("Copying key material to an AES-CTR based mode is insecure and unsupported.") # avoid breaking the deduplication by changing the id hash + old_hmac_sha256_ids = (RepoKey, KeyfileKey) + new_hmac_sha256_ids = (AESOCBRepoKey, AESOCBKeyfileKey, CHPORepoKey, CHPOKeyfileKey) + old_blake2_ids = (Blake2RepoKey, Blake2KeyfileKey) + new_blake2_ids = (Blake2AESOCBRepoKey, Blake2AESOCBKeyfileKey, Blake2CHPORepoKey, Blake2CHPOKeyfileKey) same_ids = ( - # these use HMAC-SHA256 IDs: - isinstance(other_key, (RepoKey, KeyfileKey)) - and - isinstance(key, (AESOCBRepoKey, AESOCBKeyfileKey, - CHPORepoKey, CHPOKeyfileKey)) + isinstance(other_key, old_hmac_sha256_ids + new_hmac_sha256_ids) + and isinstance(key, new_hmac_sha256_ids) or - # these use BLAKE2b IDs: - isinstance(other_key, (Blake2RepoKey, Blake2KeyfileKey)) - and - isinstance(key, (Blake2AESOCBRepoKey, Blake2AESOCBKeyfileKey, - Blake2CHPORepoKey, Blake2CHPOKeyfileKey)) + isinstance(other_key, old_blake2_ids + new_blake2_ids) + and isinstance(key, new_blake2_ids) ) if not same_ids: # either keep HMAC-SHA256 or keep BLAKE2b! From af776ce7a672f5fe8f84f28198ebdbdfff4b03a3 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 3 May 2022 21:32:35 +0200 Subject: [PATCH 2/2] refactor: borg.key.uses_same_id_hash(key_old, key_new) --- src/borg/crypto/key.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index e74847440..6ca6fbac0 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -124,6 +124,21 @@ def tam_required(repository): return os.path.isfile(file) +def uses_same_id_hash(other_key, key): + """other_key -> key upgrade: is the id hash the same?""" + # avoid breaking the deduplication by changing the id hash + old_hmac_sha256_ids = (RepoKey, KeyfileKey) + new_hmac_sha256_ids = (AESOCBRepoKey, AESOCBKeyfileKey, CHPORepoKey, CHPOKeyfileKey) + old_blake2_ids = (Blake2RepoKey, Blake2KeyfileKey) + new_blake2_ids = (Blake2AESOCBRepoKey, Blake2AESOCBKeyfileKey, Blake2CHPORepoKey, Blake2CHPOKeyfileKey) + same_ids = ( + isinstance(other_key, old_hmac_sha256_ids + new_hmac_sha256_ids) and isinstance(key, new_hmac_sha256_ids) + or + isinstance(other_key, old_blake2_ids + new_blake2_ids) and isinstance(key, new_blake2_ids) + ) + return same_ids + + class KeyBase: # Numeric key type ID, must fit in one byte. TYPE = None # override in subclasses @@ -595,20 +610,7 @@ def create(cls, repository, args, *, other_key=None): if isinstance(key, AESKeyBase): # user must use an AEADKeyBase subclass (AEAD modes with session keys) raise Error("Copying key material to an AES-CTR based mode is insecure and unsupported.") - # avoid breaking the deduplication by changing the id hash - old_hmac_sha256_ids = (RepoKey, KeyfileKey) - new_hmac_sha256_ids = (AESOCBRepoKey, AESOCBKeyfileKey, CHPORepoKey, CHPOKeyfileKey) - old_blake2_ids = (Blake2RepoKey, Blake2KeyfileKey) - new_blake2_ids = (Blake2AESOCBRepoKey, Blake2AESOCBKeyfileKey, Blake2CHPORepoKey, Blake2CHPOKeyfileKey) - same_ids = ( - isinstance(other_key, old_hmac_sha256_ids + new_hmac_sha256_ids) - and isinstance(key, new_hmac_sha256_ids) - or - isinstance(other_key, old_blake2_ids + new_blake2_ids) - and isinstance(key, new_blake2_ids) - ) - if not same_ids: - # either keep HMAC-SHA256 or keep BLAKE2b! + if not uses_same_id_hash(other_key, key): raise Error("You must keep the same ID hash (HMAC-SHA256 or BLAKE2b) or deduplication will break.") key.init_from_given_data( enc_key=other_key.enc_key,