diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 318a8f20e..54215799d 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -46,7 +46,7 @@ try: from .constants import * # NOQA from .compress import CompressionSpec from .crypto.key import key_creator, key_argument_names, tam_required_file, tam_required - from .crypto.key import RepoKey, KeyfileKey, Blake2RepoKey, Blake2KeyfileKey + from .crypto.key import RepoKey, KeyfileKey, Blake2RepoKey, Blake2KeyfileKey, FlexiKey from .crypto.keymanager import KeyManager from .helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE from .helpers import Error, NoManifestError, set_ec @@ -626,7 +626,7 @@ class Archiver: print("KDFs (slow is GOOD, use argon2!) ===============================") count = 5 for spec, func in [ - ("pbkdf2", lambda: Passphrase('mypassphrase').kdf(b'salt'*8, PBKDF2_ITERATIONS, 32)), + ("pbkdf2", lambda: FlexiKey.pbkdf2(Passphrase('mypassphrase'), b'salt'*8, PBKDF2_ITERATIONS, 32)), ("argon2", lambda: Passphrase('mypassphrase').argon2(64, b'S' * ARGON2_SALT_BYTES, **ARGON2_ARGS)), ]: print(f"{spec:<24} {count:<10} {timeit(func, number=count):.3f}s") diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index d117b6583..bf5feb449 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -3,7 +3,7 @@ import hmac import os import textwrap from binascii import a2b_base64, b2a_base64, hexlify -from hashlib import sha256 +from hashlib import sha256, pbkdf2_hmac from ..logger import create_logger @@ -447,8 +447,14 @@ class FlexiKey: else: raise UnsupportedKeyFormatError() + @staticmethod + def pbkdf2(passphrase, salt, iterations, output_len_in_bytes): + if os.environ.get("BORG_TESTONLY_WEAKEN_KDF") == "1": + iterations = 1 + return pbkdf2_hmac('sha256', passphrase.encode('utf-8'), salt, iterations, output_len_in_bytes) + def decrypt_key_file_pbkdf2(self, encrypted_key, passphrase): - key = passphrase.kdf(encrypted_key.salt, encrypted_key.iterations, 32) + key = self.pbkdf2(passphrase, encrypted_key.salt, encrypted_key.iterations, 32) data = AES(key, b'\0'*16).decrypt(encrypted_key.data) if hmac.compare_digest(hmac_sha256(key, data), encrypted_key.hash): return data @@ -485,7 +491,7 @@ class FlexiKey: def encrypt_key_file_pbkdf2(self, data, passphrase): salt = os.urandom(32) iterations = PBKDF2_ITERATIONS - key = passphrase.kdf(salt, iterations, 32) + key = self.pbkdf2(passphrase, salt, iterations, 32) hash = hmac_sha256(key, data) cdata = AES(key, b'\0'*16).encrypt(data) enc_key = EncryptedKey( diff --git a/src/borg/helpers/passphrase.py b/src/borg/helpers/passphrase.py index 52ecc11bb..704d67cc6 100644 --- a/src/borg/helpers/passphrase.py +++ b/src/borg/helpers/passphrase.py @@ -3,7 +3,6 @@ import os import shlex import subprocess import sys -from hashlib import pbkdf2_hmac from typing import Literal from . import bin_to_hex @@ -140,11 +139,6 @@ class Passphrase(str): def __repr__(self): return '' - def kdf(self, salt, iterations, length): - if os.environ.get("BORG_TESTONLY_WEAKEN_KDF") == "1": - iterations = 1 - return pbkdf2_hmac('sha256', self.encode('utf-8'), salt, iterations, length) - def argon2( self, output_len_in_bytes: int, diff --git a/src/borg/testsuite/crypto.py b/src/borg/testsuite/crypto.py index 3465bb8ff..a907c910c 100644 --- a/src/borg/testsuite/crypto.py +++ b/src/borg/testsuite/crypto.py @@ -10,7 +10,7 @@ from ..crypto.low_level import AES256_CTR_HMAC_SHA256, AES256_OCB, CHACHA20_POLY from ..crypto.low_level import bytes_to_long, bytes_to_int, long_to_bytes from ..crypto.low_level import hkdf_hmac_sha512 from ..crypto.low_level import AES, hmac_sha256 -from ..crypto.key import KeyfileKey, UnsupportedKeyFormatError, RepoKey +from ..crypto.key import KeyfileKey, UnsupportedKeyFormatError, RepoKey, FlexiKey from ..helpers.passphrase import Passphrase from ..helpers import msgpack from ..constants import KEY_ALGORITHMS @@ -294,9 +294,8 @@ def test_decrypt_key_file_argon2_aes256_ctr_hmac_sha256(monkeypatch): def test_decrypt_key_file_pbkdf2_sha256_aes256_ctr_hmac_sha256(monkeypatch): plain = b'hello' salt = b'salt'*4 - monkeypatch.setenv('BORG_PASSPHRASE', "hello, pass phrase") - passphrase = Passphrase.new() - key = passphrase.kdf(salt, iterations=1, length=32) + passphrase = Passphrase("hello, pass phrase") + key = FlexiKey.pbkdf2(passphrase, salt, 1, 32) hash = hmac_sha256(key, plain) data = AES(key, b'\0'*16).encrypt(plain) encrypted = msgpack.packb({