diff --git a/src/borg/constants.py b/src/borg/constants.py index 208991ee7..0b2ef16a1 100644 --- a/src/borg/constants.py +++ b/src/borg/constants.py @@ -112,8 +112,8 @@ ARGON2_SALT_BYTES = 16 KEY_ALGORITHMS = { # encrypt-and-MAC, kdf: PBKDF2(HMAC−SHA256), encryption: AES256-CTR, authentication: HMAC-SHA256 'pbkdf2': 'sha256', - # encrypt-then-MAC, kdf: argon2, encryption: AES256-CTR, authentication: HMAC-SHA256 - 'argon2': 'argon2 aes256-ctr hmac-sha256', + # encrypt-then-MAC, kdf: argon2, encryption: chacha20, authentication: poly1305 + 'argon2': 'argon2 chacha20-poly1305', } diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index 879f85c88..ad4cab9d4 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -445,7 +445,7 @@ class FlexiKey: self._encrypted_key_algorithm = encrypted_key.algorithm if encrypted_key.algorithm == 'sha256': return self.decrypt_key_file_pbkdf2(encrypted_key, passphrase) - elif encrypted_key.algorithm == 'argon2 aes256-ctr hmac-sha256': + elif encrypted_key.algorithm == 'argon2 chacha20-poly1305': return self.decrypt_key_file_argon2(encrypted_key, passphrase) else: raise UnsupportedKeyFormatError() @@ -497,19 +497,14 @@ class FlexiKey: def decrypt_key_file_argon2(self, encrypted_key, passphrase): key = self.argon2( passphrase, - output_len_in_bytes=64, + output_len_in_bytes=32, salt=encrypted_key.salt, time_cost=encrypted_key.argon2_time_cost, memory_cost=encrypted_key.argon2_memory_cost, parallelism=encrypted_key.argon2_parallelism, type=encrypted_key.argon2_type, ) - enc_key, mac_key = key[:32], key[32:] - ae_cipher = AES256_CTR_HMAC_SHA256( - iv=0, header_len=0, aad_offset=0, - enc_key=enc_key, - mac_key=mac_key, - ) + ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0) try: return ae_cipher.decrypt(encrypted_key.data) except low_level.IntegrityError: @@ -518,7 +513,7 @@ class FlexiKey: def encrypt_key_file(self, data, passphrase, algorithm): if algorithm == 'sha256': return self.encrypt_key_file_pbkdf2(data, passphrase) - elif algorithm == 'argon2 aes256-ctr hmac-sha256': + elif algorithm == 'argon2 chacha20-poly1305': return self.encrypt_key_file_argon2(data, passphrase) else: raise ValueError(f'Unexpected algorithm: {algorithm}') @@ -543,19 +538,14 @@ class FlexiKey: salt = os.urandom(ARGON2_SALT_BYTES) key = self.argon2( passphrase, - output_len_in_bytes=64, + output_len_in_bytes=32, salt=salt, **ARGON2_ARGS, ) - enc_key, mac_key = key[:32], key[32:] - ae_cipher = AES256_CTR_HMAC_SHA256( - iv=0, header_len=0, aad_offset=0, - enc_key=enc_key, - mac_key=mac_key, - ) + ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0) encrypted_key = EncryptedKey( version=1, - algorithm='argon2 aes256-ctr hmac-sha256', + algorithm='argon2 chacha20-poly1305', salt=salt, data=ae_cipher.encrypt(data), **{'argon2_' + k: v for k, v in ARGON2_ARGS.items()}, diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index 76d615f6b..445ebac2a 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -3600,7 +3600,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 self.cmd('init', '--encryption=repokey', self.repository_location) with Repository(self.repository_path) as repository: key = msgpack.unpackb(a2b_base64(repository.load_key())) - assert key[b'algorithm'] == b'argon2 aes256-ctr hmac-sha256' + assert key[b'algorithm'] == b'argon2 chacha20-poly1305' def test_init_with_explicit_key_algorithm(self): """https://github.com/borgbackup/borg/issues/747#issuecomment-1076160401""" @@ -3620,7 +3620,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 assert key[b'algorithm'] == expected_algorithm def test_change_passphrase_does_not_change_algorithm_argon2(self): - self.verify_change_passphrase_does_not_change_algorithm('argon2', b'argon2 aes256-ctr hmac-sha256') + self.verify_change_passphrase_does_not_change_algorithm('argon2', b'argon2 chacha20-poly1305') def test_change_passphrase_does_not_change_algorithm_pbkdf2(self): self.verify_change_passphrase_does_not_change_algorithm('pbkdf2', b'sha256') @@ -3635,7 +3635,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 assert key[b'algorithm'] == expected_algorithm def test_change_location_does_not_change_algorithm_argon2(self): - self.verify_change_location_does_not_change_algorithm('argon2', b'argon2 aes256-ctr hmac-sha256') + self.verify_change_location_does_not_change_algorithm('argon2', b'argon2 chacha20-poly1305') def test_change_location_does_not_change_algorithm_pbkdf2(self): self.verify_change_location_does_not_change_algorithm('pbkdf2', b'sha256') @@ -3647,7 +3647,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 with Repository(self.repository_path) as repository: _, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) - assert key._encrypted_key_algorithm == 'argon2 aes256-ctr hmac-sha256' + assert key._encrypted_key_algorithm == 'argon2 chacha20-poly1305' self.cmd('info', self.repository_location) diff --git a/src/borg/testsuite/crypto.py b/src/borg/testsuite/crypto.py index 570afbc1d..dac3efeb3 100644 --- a/src/borg/testsuite/crypto.py +++ b/src/borg/testsuite/crypto.py @@ -247,15 +247,11 @@ class CryptoTestCase(BaseTestCase): assert okm == bytes.fromhex('1407d46013d98bc6decefcfee55f0f90b0c7f63d68eb1a80eaf07e953cfc0a3a5240a155d6e4daa965bb') -def test_decrypt_key_file_argon2_aes256_ctr_hmac_sha256(): +def test_decrypt_key_file_argon2_chacha20_poly1305(): plain = b'hello' - # echo -n "hello, pass phrase" | argon2 saltsaltsaltsalt -id -t 1 -k 8 -p 1 -l 64 -r - key = bytes.fromhex('d07cc7f9cfb483303e0b9fec176b2a9c559bb70c3a9fb0d5f9c0c23527cd09570212449f09f8cd28c1a41b73fa0098e889c3f2642e87c392e51f95d70d248d9d') - ae_cipher = AES256_CTR_HMAC_SHA256( - iv=0, header_len=0, aad_offset=0, - enc_key=key[:32], - mac_key=key[32:], - ) + # echo -n "hello, pass phrase" | argon2 saltsaltsaltsalt -id -t 1 -k 8 -p 1 -l 32 -r + key = bytes.fromhex('a1b0cba145c154fbd8960996c5ce3428e9920cfe53c84ef08b4102a70832bcec') + ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0) envelope = ae_cipher.encrypt(plain) @@ -266,7 +262,7 @@ def test_decrypt_key_file_argon2_aes256_ctr_hmac_sha256(): 'argon2_memory_cost': 8, 'argon2_parallelism': 1, 'argon2_type': b'id', - 'algorithm': 'argon2 aes256-ctr hmac-sha256', + 'algorithm': 'argon2 chacha20-poly1305', 'data': envelope, }) key = KeyfileKey(None)