mirror of
https://github.com/borgbackup/borg.git
synced 2025-03-10 06:03:38 +00:00
rebuild_refcounts: keep archive ID, if possible
rebuild_refcounts verifies and recreates the TAM. Now it re-uses the salt, so that the archive ID does not change just because of a new salt if the archive has still the same data.
This commit is contained in:
parent
85b173d3d1
commit
d78ed697ae
4 changed files with 14 additions and 12 deletions
|
@ -490,7 +490,7 @@ class Archive:
|
|||
def _load_meta(self, id):
|
||||
data = self.key.decrypt(id, self.repository.get(id))
|
||||
# we do not require TAM for archives, otherwise we can not even borg list a repo with old archives.
|
||||
archive, self.tam_verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
archive, self.tam_verified, _ = self.key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
metadata = ArchiveItem(internal_dict=archive)
|
||||
if metadata.version != 1:
|
||||
raise Exception('Unknown archive metadata version')
|
||||
|
@ -1819,7 +1819,7 @@ class ArchiveChecker:
|
|||
# **after** doing the low-level checks and having a strong indication that we
|
||||
# are likely looking at an archive item here, also check the TAM authentication:
|
||||
try:
|
||||
archive, verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
archive, verified, _ = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
except IntegrityError:
|
||||
# TAM issues - do not accept this archive!
|
||||
# either somebody is trying to attack us with a fake archive data or
|
||||
|
@ -2065,7 +2065,7 @@ class ArchiveChecker:
|
|||
del self.manifest.archives[info.name]
|
||||
continue
|
||||
try:
|
||||
archive, verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
archive, verified, salt = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
except IntegrityError as integrity_error:
|
||||
# looks like there is a TAM issue with this archive, this might be an attack!
|
||||
# when upgrading to borg 1.2.5, users are expected to TAM-authenticate all archives they
|
||||
|
@ -2088,7 +2088,7 @@ class ArchiveChecker:
|
|||
for previous_item_id in archive.items:
|
||||
mark_as_possibly_superseded(previous_item_id)
|
||||
archive.items = items_buffer.chunks
|
||||
data = self.key.pack_and_authenticate_metadata(archive.as_dict(), context=b'archive')
|
||||
data = self.key.pack_and_authenticate_metadata(archive.as_dict(), context=b'archive', salt=salt)
|
||||
new_archive_id = self.key.id_hash(data)
|
||||
cdata = self.key.encrypt(data)
|
||||
add_reference(new_archive_id, len(data), len(cdata), cdata)
|
||||
|
|
|
@ -1630,7 +1630,7 @@ class Archiver:
|
|||
archive_formatted = format_archive(info)
|
||||
cdata = repository.get(archive_id)
|
||||
data = key.decrypt(archive_id, cdata)
|
||||
archive, verified = key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
archive, verified, _ = key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
if not verified: # we do not have an archive TAM yet -> add TAM now!
|
||||
archive = ArchiveItem(internal_dict=archive)
|
||||
archive.cmdline = [safe_decode(arg) for arg in archive.cmdline]
|
||||
|
|
|
@ -755,7 +755,7 @@ class LocalCache(CacheStatsMixin):
|
|||
nonlocal processed_item_metadata_chunks
|
||||
csize, data = decrypted_repository.get(archive_id)
|
||||
chunk_idx.add(archive_id, 1, len(data), csize)
|
||||
archive, verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
archive, verified, _ = self.key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
archive = ArchiveItem(internal_dict=archive)
|
||||
if archive.version != 1:
|
||||
raise Exception('Unknown archive metadata version')
|
||||
|
|
|
@ -226,15 +226,17 @@ class KeyBase:
|
|||
output_length=64
|
||||
)
|
||||
|
||||
def pack_and_authenticate_metadata(self, metadata_dict, context=b'manifest'):
|
||||
def pack_and_authenticate_metadata(self, metadata_dict, context=b'manifest', salt=None):
|
||||
if salt is None:
|
||||
salt = os.urandom(64)
|
||||
metadata_dict = StableDict(metadata_dict)
|
||||
tam = metadata_dict['tam'] = StableDict({
|
||||
'type': 'HKDF_HMAC_SHA512',
|
||||
'hmac': bytes(64),
|
||||
'salt': os.urandom(64),
|
||||
'salt': salt,
|
||||
})
|
||||
packed = msgpack.packb(metadata_dict)
|
||||
tam_key = self._tam_key(tam['salt'], context)
|
||||
tam_key = self._tam_key(salt, context)
|
||||
tam['hmac'] = hmac.digest(tam_key, packed, 'sha512')
|
||||
return msgpack.packb(metadata_dict)
|
||||
|
||||
|
@ -300,7 +302,7 @@ class KeyBase:
|
|||
raise ArchiveTAMRequiredError(archive_name)
|
||||
else:
|
||||
logger.debug('Archive TAM not found and not required')
|
||||
return unpacked, False
|
||||
return unpacked, False, None
|
||||
tam = unpacked.pop(b'tam', None)
|
||||
if not isinstance(tam, dict):
|
||||
raise ArchiveTAMInvalid()
|
||||
|
@ -310,7 +312,7 @@ class KeyBase:
|
|||
raise TAMUnsupportedSuiteError(repr(tam_type))
|
||||
else:
|
||||
logger.debug('Ignoring archive TAM made with unsupported suite, since TAM is not required: %r', tam_type)
|
||||
return unpacked, False
|
||||
return unpacked, False, None
|
||||
tam_hmac = tam.get(b'hmac')
|
||||
tam_salt = tam.get(b'salt')
|
||||
if not isinstance(tam_salt, bytes) or not isinstance(tam_hmac, bytes):
|
||||
|
@ -322,7 +324,7 @@ class KeyBase:
|
|||
if not hmac.compare_digest(calculated_hmac, tam_hmac):
|
||||
raise ArchiveTAMInvalid()
|
||||
logger.debug('TAM-verified archive')
|
||||
return unpacked, True
|
||||
return unpacked, True, tam_salt
|
||||
|
||||
|
||||
class PlaintextKey(KeyBase):
|
||||
|
|
Loading…
Add table
Reference in a new issue