Merge pull request #7702 from ThomasWaldmann/authenticated-no-key-1.2

BORG_WORKAROUNDS=authenticated_no_key, fixes #7700
This commit is contained in:
TW 2023-07-07 01:02:41 +02:00 committed by GitHub
commit 4721a35863
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 0 deletions

View File

@ -100,6 +100,22 @@ General:
caused EROFS. You will need this to make archives from volume shadow copies
in WSL1 (Windows Subsystem for Linux 1).
authenticated_no_key
Work around a lost passphrase or key for an ``authenticated`` mode repository
(these are only authenticated, but not encrypted).
If the key is missing in the repository config, add ``key = anything`` there.
This workaround is **only** for emergencies and **only** to extract data
from an affected repository (read-only access)::
BORG_WORKAROUNDS=authenticated_no_key borg extract repo::archive
After you have extracted all data you need, you MUST delete the repository::
BORG_WORKAROUNDS=authenticated_no_key borg delete repo
Now you can init a fresh repo. Make sure you do not use the workaround any more.
Some automatic "answerers" (if set, they automatically answer confirmation questions):
BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=no (or =yes)
For "Warning: Attempting to access a previously unknown unencrypted repository"

View File

@ -4227,6 +4227,8 @@ class Archiver:
If you do **not** want to encrypt the contents of your backups, but still
want to detect malicious tampering use ``--encryption authenticated``.
To normally work with ``authenticated`` repos, you will need the passphrase, but
there is an emergency workaround, see ``BORG_WORKAROUNDS=authenticated_no_key`` docs.
If ``BLAKE2b`` is faster than ``SHA-256`` on your hardware, use ``--encryption authenticated-blake2``,
``--encryption repokey-blake2`` or ``--encryption keyfile-blake2``. Note: for remote backups

View File

@ -24,6 +24,7 @@ from ..helpers import get_limited_unpacker
from ..helpers import bin_to_hex
from ..helpers import prepare_subprocess_env
from ..helpers import msgpack
from ..helpers import workarounds
from ..item import Key, EncryptedKey
from ..platform import SaveFile
@ -32,6 +33,10 @@ from .low_level import AES, bytes_to_long, long_to_bytes, bytes_to_int, num_ciph
from .low_level import AES256_CTR_HMAC_SHA256, AES256_CTR_BLAKE2b
# workaround for lost passphrase or key in "authenticated" or "authenticated-blake2" mode
AUTHENTICATED_NO_KEY = 'authenticated_no_key' in workarounds
class NoPassphraseFailure(Error):
"""can not acquire a passphrase: {}"""
@ -253,6 +258,8 @@ class KeyBase:
offset = data.index(tam_hmac)
data[offset:offset + 64] = bytes(64)
tam_key = self._tam_key(tam_salt, context=b'manifest')
if AUTHENTICATED_NO_KEY:
return unpacked, True # True is a lie.
calculated_hmac = hmac.digest(tam_key, data, 'sha512')
if not hmac.compare_digest(calculated_hmac, tam_hmac):
raise TAMInvalid()
@ -874,6 +881,19 @@ class AuthenticatedKeyBase(RepoKey):
# It's only authenticated, not encrypted.
logically_encrypted = False
def _load(self, key_data, passphrase):
if AUTHENTICATED_NO_KEY:
# fake _load if we have no key or passphrase
NOPE = bytes(32) # 256 bit all-zero
self.repository_id = NOPE
self.enc_key = NOPE
self.enc_hmac_key = NOPE
self.id_key = NOPE
self.chunk_seed = 0
self.tam_required = False
return True
return super()._load(key_data, passphrase)
def load(self, target, passphrase):
success = super().load(target, passphrase)
self.logically_encrypted = False
@ -899,6 +919,8 @@ class AuthenticatedKeyBase(RepoKey):
if not decompress:
return payload
data = self.decompress(payload)
if AUTHENTICATED_NO_KEY:
return data
self.assert_id(id, data)
return data