Merge pull request #6604 from ThomasWaldmann/argon2-chacha

argon2 key: use chacha20-poly1305 instead of aes256-ctr+hmac-sha256
This commit is contained in:
TW 2022-04-17 07:10:46 +02:00 committed by GitHub
commit 7fd53903f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 32 deletions

View File

@ -112,8 +112,8 @@ ARGON2_SALT_BYTES = 16
KEY_ALGORITHMS = { KEY_ALGORITHMS = {
# encrypt-and-MAC, kdf: PBKDF2(HMACSHA256), encryption: AES256-CTR, authentication: HMAC-SHA256 # encrypt-and-MAC, kdf: PBKDF2(HMACSHA256), encryption: AES256-CTR, authentication: HMAC-SHA256
'pbkdf2': 'sha256', 'pbkdf2': 'sha256',
# encrypt-then-MAC, kdf: argon2, encryption: AES256-CTR, authentication: HMAC-SHA256 # encrypt-then-MAC, kdf: argon2, encryption: chacha20, authentication: poly1305
'argon2': 'argon2 aes256-ctr hmac-sha256', 'argon2': 'argon2 chacha20-poly1305',
} }

View File

@ -445,7 +445,7 @@ class FlexiKey:
self._encrypted_key_algorithm = encrypted_key.algorithm self._encrypted_key_algorithm = encrypted_key.algorithm
if encrypted_key.algorithm == 'sha256': if encrypted_key.algorithm == 'sha256':
return self.decrypt_key_file_pbkdf2(encrypted_key, passphrase) 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) return self.decrypt_key_file_argon2(encrypted_key, passphrase)
else: else:
raise UnsupportedKeyFormatError() raise UnsupportedKeyFormatError()
@ -497,19 +497,14 @@ class FlexiKey:
def decrypt_key_file_argon2(self, encrypted_key, passphrase): def decrypt_key_file_argon2(self, encrypted_key, passphrase):
key = self.argon2( key = self.argon2(
passphrase, passphrase,
output_len_in_bytes=64, output_len_in_bytes=32,
salt=encrypted_key.salt, salt=encrypted_key.salt,
time_cost=encrypted_key.argon2_time_cost, time_cost=encrypted_key.argon2_time_cost,
memory_cost=encrypted_key.argon2_memory_cost, memory_cost=encrypted_key.argon2_memory_cost,
parallelism=encrypted_key.argon2_parallelism, parallelism=encrypted_key.argon2_parallelism,
type=encrypted_key.argon2_type, type=encrypted_key.argon2_type,
) )
enc_key, mac_key = key[:32], key[32:] ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0)
ae_cipher = AES256_CTR_HMAC_SHA256(
iv=0, header_len=0, aad_offset=0,
enc_key=enc_key,
mac_key=mac_key,
)
try: try:
return ae_cipher.decrypt(encrypted_key.data) return ae_cipher.decrypt(encrypted_key.data)
except low_level.IntegrityError: except low_level.IntegrityError:
@ -518,7 +513,7 @@ class FlexiKey:
def encrypt_key_file(self, data, passphrase, algorithm): def encrypt_key_file(self, data, passphrase, algorithm):
if algorithm == 'sha256': if algorithm == 'sha256':
return self.encrypt_key_file_pbkdf2(data, passphrase) 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) return self.encrypt_key_file_argon2(data, passphrase)
else: else:
raise ValueError(f'Unexpected algorithm: {algorithm}') raise ValueError(f'Unexpected algorithm: {algorithm}')
@ -543,19 +538,14 @@ class FlexiKey:
salt = os.urandom(ARGON2_SALT_BYTES) salt = os.urandom(ARGON2_SALT_BYTES)
key = self.argon2( key = self.argon2(
passphrase, passphrase,
output_len_in_bytes=64, output_len_in_bytes=32,
salt=salt, salt=salt,
**ARGON2_ARGS, **ARGON2_ARGS,
) )
enc_key, mac_key = key[:32], key[32:] ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0)
ae_cipher = AES256_CTR_HMAC_SHA256(
iv=0, header_len=0, aad_offset=0,
enc_key=enc_key,
mac_key=mac_key,
)
encrypted_key = EncryptedKey( encrypted_key = EncryptedKey(
version=1, version=1,
algorithm='argon2 aes256-ctr hmac-sha256', algorithm='argon2 chacha20-poly1305',
salt=salt, salt=salt,
data=ae_cipher.encrypt(data), data=ae_cipher.encrypt(data),
**{'argon2_' + k: v for k, v in ARGON2_ARGS.items()}, **{'argon2_' + k: v for k, v in ARGON2_ARGS.items()},

View File

@ -3600,7 +3600,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
self.cmd('init', '--encryption=repokey', self.repository_location) self.cmd('init', '--encryption=repokey', self.repository_location)
with Repository(self.repository_path) as repository: with Repository(self.repository_path) as repository:
key = msgpack.unpackb(a2b_base64(repository.load_key())) 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): def test_init_with_explicit_key_algorithm(self):
"""https://github.com/borgbackup/borg/issues/747#issuecomment-1076160401""" """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 assert key[b'algorithm'] == expected_algorithm
def test_change_passphrase_does_not_change_algorithm_argon2(self): 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): def test_change_passphrase_does_not_change_algorithm_pbkdf2(self):
self.verify_change_passphrase_does_not_change_algorithm('pbkdf2', b'sha256') 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 assert key[b'algorithm'] == expected_algorithm
def test_change_location_does_not_change_algorithm_argon2(self): 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): def test_change_location_does_not_change_algorithm_pbkdf2(self):
self.verify_change_location_does_not_change_algorithm('pbkdf2', b'sha256') 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: with Repository(self.repository_path) as repository:
_, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) _, 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) self.cmd('info', self.repository_location)

View File

@ -247,15 +247,11 @@ class CryptoTestCase(BaseTestCase):
assert okm == bytes.fromhex('1407d46013d98bc6decefcfee55f0f90b0c7f63d68eb1a80eaf07e953cfc0a3a5240a155d6e4daa965bb') 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' plain = b'hello'
# echo -n "hello, pass phrase" | argon2 saltsaltsaltsalt -id -t 1 -k 8 -p 1 -l 64 -r # echo -n "hello, pass phrase" | argon2 saltsaltsaltsalt -id -t 1 -k 8 -p 1 -l 32 -r
key = bytes.fromhex('d07cc7f9cfb483303e0b9fec176b2a9c559bb70c3a9fb0d5f9c0c23527cd09570212449f09f8cd28c1a41b73fa0098e889c3f2642e87c392e51f95d70d248d9d') key = bytes.fromhex('a1b0cba145c154fbd8960996c5ce3428e9920cfe53c84ef08b4102a70832bcec')
ae_cipher = AES256_CTR_HMAC_SHA256( ae_cipher = CHACHA20_POLY1305(key=key, iv=0, header_len=0, aad_offset=0)
iv=0, header_len=0, aad_offset=0,
enc_key=key[:32],
mac_key=key[32:],
)
envelope = ae_cipher.encrypt(plain) envelope = ae_cipher.encrypt(plain)
@ -266,7 +262,7 @@ def test_decrypt_key_file_argon2_aes256_ctr_hmac_sha256():
'argon2_memory_cost': 8, 'argon2_memory_cost': 8,
'argon2_parallelism': 1, 'argon2_parallelism': 1,
'argon2_type': b'id', 'argon2_type': b'id',
'algorithm': 'argon2 aes256-ctr hmac-sha256', 'algorithm': 'argon2 chacha20-poly1305',
'data': envelope, 'data': envelope,
}) })
key = KeyfileKey(None) key = KeyfileKey(None)