Skip to content

Commit

Permalink
new crypto does not need to call ._assert_id()
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasWaldmann committed Jul 20, 2022
1 parent 0037375 commit f82f123
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/borg/crypto/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,10 @@ def decrypt(self, id, data, decompress=True):
if not decompress:
return payload
data = self.decompress(memoryview(payload))
self.assert_id(id, data)
# note: calling self.assert_id(id, data) is not needed any more for the new AEAD crypto.
# we put the id into AAD when storing the chunk, so it gets into the authentication tag computation.
# when decrypting, we provide the id we **want** as AAD for the auth tag verification, so
# decrypting only succeeds if we got the ciphertext we wrote **for that chunk id**.
return data

def init_from_given_data(self, *, enc_key, enc_hmac_key, id_key, chunk_seed):
Expand Down
21 changes: 21 additions & 0 deletions src/borg/testsuite/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@ def test_assert_id(self, key):
with pytest.raises(IntegrityError):
key.assert_id(id, plaintext_changed)

def test_getting_wrong_chunk_fails(self, key):
# for the new AEAD crypto, we provide the chunk id as AAD when encrypting/authenticating,
# we provide the id **we want** as AAD when authenticating/decrypting the data we got from the repo.
# only if the id used for encrypting matches the id we want, the AEAD crypto authentication will succeed.
# thus, there is no need any more for calling self._assert_id() for the new crypto.
# the old crypto as well as plaintext and authenticated modes still need to call self._assert_id().
plaintext_wanted = b"123456789"
id_wanted = key.id_hash(plaintext_wanted)
ciphertext_wanted = key.encrypt(id_wanted, plaintext_wanted)
plaintext_other = b"xxxxxxxxx"
id_other = key.id_hash(plaintext_other)
ciphertext_other = key.encrypt(id_other, plaintext_other)
# both ciphertexts are authentic and decrypting them should succeed:
key.decrypt(id_wanted, ciphertext_wanted)
key.decrypt(id_other, ciphertext_other)
# but if we wanted the one and got the other, it must fail.
# the new crypto will fail due to AEAD auth failure,
# the old crypto and plaintext, authenticated modes will fail due to ._assert_id() check failing:
with pytest.raises(IntegrityErrorBase):
key.decrypt(id_wanted, ciphertext_other)

def test_authenticated_encrypt(self, monkeypatch):
monkeypatch.setenv("BORG_PASSPHRASE", "test")
key = AuthenticatedKey.create(self.MockRepository(), self.MockArgs())
Expand Down

0 comments on commit f82f123

Please sign in to comment.