transfer: check whether ID hash method and chunker secret are same, fixes #6893

also: add PlaintextKey and AuthenticatedKey support to uses_same_id_hash function.
This commit is contained in:
Thomas Waldmann 2022-08-01 13:25:28 +02:00
parent c5a594688a
commit a8dda5cb0c
2 changed files with 35 additions and 5 deletions

View File

@ -3,6 +3,7 @@ import argparse
from .common import with_repository, with_other_repository
from ..archive import Archive
from ..constants import * # NOQA
from ..crypto.key import uses_same_id_hash, uses_same_chunker_secret
from ..helpers import EXIT_SUCCESS, EXIT_ERROR
from ..helpers import location_validator, Location
from ..helpers import format_file_size
@ -20,6 +21,18 @@ class TransferMixIn:
self, args, *, repository, manifest, key, cache, other_repository=None, other_manifest=None, other_key=None
):
"""archives transfer from other repository, optionally upgrade data format"""
if not uses_same_id_hash(other_key, key):
self.print_error(
"You must keep the same ID hash ([HMAC-]SHA256 or BLAKE2b) or deduplication will break. "
"Use a related repository!"
)
return EXIT_ERROR
if not uses_same_chunker_secret(other_key, key):
self.print_error(
"You must use the same chunker secret or deduplication will break. " "Use a related repository!"
)
return EXIT_ERROR
dry_run = args.dry_run
args.consider_checkpoints = True
archive_names = tuple(x.name for x in other_manifest.archives.list_considering(args))
@ -106,7 +119,7 @@ class TransferMixIn:
# initialize DST_REPO reusing key material from SRC_REPO, so that
# chunking and chunk id generation will work in the same way as before.
borg --repo=DST_REPO init --other-repo=SRC_REPO --encryption=DST_ENC
borg --repo=DST_REPO rcreate --other-repo=SRC_REPO --encryption=DST_ENC
# transfer archives from SRC_REPO to DST_REPO
borg --repo=DST_REPO transfer --other-repo=SRC_REPO --dry-run # check what it would do

View File

@ -121,18 +121,35 @@ def tam_required(repository):
return os.path.isfile(file)
def uses_same_chunker_secret(other_key, key):
"""is the chunker secret the same?"""
# avoid breaking the deduplication by a different chunker secret
same_chunker_secret = other_key.chunk_seed == key.chunk_seed
return same_chunker_secret
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)
old_sha256_ids = (PlaintextKey,)
new_sha256_ids = (PlaintextKey,)
old_hmac_sha256_ids = (RepoKey, KeyfileKey, AuthenticatedKey)
new_hmac_sha256_ids = (AESOCBRepoKey, AESOCBKeyfileKey, CHPORepoKey, CHPOKeyfileKey, AuthenticatedKey)
old_blake2_ids = (Blake2RepoKey, Blake2KeyfileKey, Blake2AuthenticatedKey)
new_blake2_ids = (
Blake2AESOCBRepoKey,
Blake2AESOCBKeyfileKey,
Blake2CHPORepoKey,
Blake2CHPOKeyfileKey,
Blake2AuthenticatedKey,
)
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)
or isinstance(other_key, old_sha256_ids + new_sha256_ids)
and isinstance(key, new_sha256_ids)
)
return same_ids