mirror of
https://github.com/borgbackup/borg.git
synced 2026-02-20 00:10:35 -05:00
Rename Key.passphrase_protected -> logically_encrypted & document
This commit is contained in:
parent
cad49b844e
commit
848df38d08
3 changed files with 32 additions and 12 deletions
|
|
@ -133,15 +133,18 @@ Version 1.1.0b6 (unreleased)
|
|||
|
||||
Compatibility notes:
|
||||
|
||||
- Repositories in a repokey mode (including "authenticated" mode) with a
|
||||
blank passphrase are now treated as unencrypted repositories for security checks
|
||||
- Repositories in the "repokey" and "repokey-blake2" modes with an empty passphrase
|
||||
are now treated as unencrypted repositories for security checks
|
||||
(e.g. BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK).
|
||||
- Running "borg init" via a "borg serve --append-only" server will *not* create
|
||||
an append-only repository anymore. Use "borg init --append-only" to initialize
|
||||
an append-only repository.
|
||||
|
||||
Repositories in the "authenticated" mode are now treated as the unencrypted repositories
|
||||
they are.
|
||||
|
||||
Previously there would be no prompts nor messages if an unknown repository
|
||||
in one of these modes with a blank passphrase was encountered. This would
|
||||
in one of these modes with an empty passphrase was encountered. This would
|
||||
allow an attacker to swap a repository, if one assumed that the lack of
|
||||
password prompts was due to a set BORG_PASSPHRASE.
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class SecurityManager:
|
|||
self.save(manifest, key, cache)
|
||||
|
||||
def assert_access_unknown(self, warn_if_unencrypted, key):
|
||||
if warn_if_unencrypted and not key.passphrase_protected and not self.known():
|
||||
if warn_if_unencrypted and not key.logically_encrypted and not self.known():
|
||||
msg = ("Warning: Attempting to access a previously unknown unencrypted repository!\n" +
|
||||
"Do you want to continue? [yN] ")
|
||||
if not yes(msg, false_msg="Aborting.", invalid_msg="Invalid answer, aborting.",
|
||||
|
|
|
|||
|
|
@ -129,15 +129,31 @@ def tam_required(repository):
|
|||
|
||||
|
||||
class KeyBase:
|
||||
# Numeric key type ID, must fit in one byte.
|
||||
TYPE = None # override in subclasses
|
||||
|
||||
# Human-readable name
|
||||
NAME = 'UNDEFINED'
|
||||
|
||||
# Name used in command line / API (e.g. borg init --encryption=...)
|
||||
ARG_NAME = 'UNDEFINED'
|
||||
|
||||
# Storage type (no key blob storage / keyfile / repo)
|
||||
STORAGE = KeyBlobStorage.NO_STORAGE
|
||||
|
||||
# Seed for the buzhash chunker (borg.algorithms.chunker.Chunker)
|
||||
# type: int
|
||||
chunk_seed = None
|
||||
|
||||
# Whether this *particular instance* is encrypted from a practical point of view,
|
||||
# i.e. when it's using encryption with a empty passphrase, then
|
||||
# that may be *technically* called encryption, but for all intents and purposes
|
||||
# that's as good as not encrypting in the first place, and this member should be False.
|
||||
#
|
||||
# The empty passphrase is also special because Borg tries it first when no passphrase
|
||||
# was supplied, and if an empty passphrase works, then Borg won't ask for one.
|
||||
logically_encrypted = False
|
||||
|
||||
def __init__(self, repository):
|
||||
self.TYPE_STR = bytes([self.TYPE])
|
||||
self.repository = repository
|
||||
|
|
@ -234,7 +250,7 @@ class PlaintextKey(KeyBase):
|
|||
STORAGE = KeyBlobStorage.NO_STORAGE
|
||||
|
||||
chunk_seed = 0
|
||||
passphrase_protected = False
|
||||
logically_encrypted = False
|
||||
|
||||
def __init__(self, repository):
|
||||
super().__init__(repository)
|
||||
|
|
@ -314,7 +330,8 @@ class ID_HMAC_SHA_256:
|
|||
|
||||
|
||||
class AESKeyBase(KeyBase):
|
||||
"""Common base class shared by KeyfileKey and PassphraseKey
|
||||
"""
|
||||
Common base class shared by KeyfileKey and PassphraseKey
|
||||
|
||||
Chunks are encrypted using 256bit AES in Counter Mode (CTR)
|
||||
|
||||
|
|
@ -330,7 +347,7 @@ class AESKeyBase(KeyBase):
|
|||
|
||||
MAC = hmac_sha256
|
||||
|
||||
passphrase_protected = True
|
||||
logically_encrypted = True
|
||||
|
||||
def encrypt(self, chunk):
|
||||
data = self.compressor.compress(chunk)
|
||||
|
|
@ -705,7 +722,7 @@ class RepoKey(ID_HMAC_SHA_256, KeyfileKeyBase):
|
|||
def load(self, target, passphrase):
|
||||
# While the repository is encrypted, we consider a repokey repository with a blank
|
||||
# passphrase an unencrypted repository.
|
||||
self.passphrase_protected = passphrase != ''
|
||||
self.logically_encrypted = passphrase != ''
|
||||
|
||||
# what we get in target is just a repo location, but we already have the repo obj:
|
||||
target = self.repository
|
||||
|
|
@ -717,7 +734,7 @@ class RepoKey(ID_HMAC_SHA_256, KeyfileKeyBase):
|
|||
return success
|
||||
|
||||
def save(self, target, passphrase):
|
||||
self.passphrase_protected = passphrase != ''
|
||||
self.logically_encrypted = passphrase != ''
|
||||
key_data = self._save(passphrase)
|
||||
key_data = key_data.encode('utf-8') # remote repo: msgpack issue #99, giving bytes
|
||||
target.save_key(key_data)
|
||||
|
|
@ -750,16 +767,16 @@ class AuthenticatedKey(ID_BLAKE2b_256, RepoKey):
|
|||
STORAGE = KeyBlobStorage.REPO
|
||||
|
||||
# It's only authenticated, not encrypted.
|
||||
passphrase_protected = False
|
||||
logically_encrypted = False
|
||||
|
||||
def load(self, target, passphrase):
|
||||
success = super().load(target, passphrase)
|
||||
self.passphrase_protected = False
|
||||
self.logically_encrypted = False
|
||||
return success
|
||||
|
||||
def save(self, target, passphrase):
|
||||
super().save(target, passphrase)
|
||||
self.passphrase_protected = False
|
||||
self.logically_encrypted = False
|
||||
|
||||
def encrypt(self, chunk):
|
||||
data = self.compressor.compress(chunk)
|
||||
|
|
|
|||
Loading…
Reference in a new issue