Browse Source

rcreate: always use argon2 kdf for new repos, fixes #6820

this way, we can remove the legacy pbkdf2 key code in next release.
Thomas Waldmann 2 năm trước cách đây
mục cha
commit
eabad3e3b7

+ 0 - 1
setup_docs.py

@@ -303,7 +303,6 @@ class build_man(Command):
 
         'key_change-passphrase': 'key',
         'key_change-location': 'key',
-        'key_change-algorithm': 'key',
         'key_export': 'key',
         'key_import': 'key',
         'key_migrate-to-repokey': 'key',

+ 0 - 58
src/borg/archiver.py

@@ -4380,22 +4380,6 @@ class Archiver:
         If you do **not** want to encrypt the contents of your backups, but still want to detect
         malicious tampering use an `authenticated` mode. It's like `repokey` minus encryption.
 
-        Key derivation functions
-        ++++++++++++++++++++++++
-
-        - ``--key-algorithm argon2`` is the default and is recommended.
-          The key encryption key is derived from your passphrase via argon2-id.
-          Argon2 is considered more modern and secure than pbkdf2.
-
-        Our implementation of argon2-based key algorithm follows the cryptographic best practices:
-
-        - It derives two separate keys from your passphrase: one to encrypt your key and another one
-          to sign it. ``--key-algorithm pbkdf2`` uses the same key for both.
-
-        - It uses encrypt-then-mac instead of encrypt-and-mac used by ``--key-algorithm pbkdf2``
-
-        Neither is inherently linked to the key derivation function, but since we were going
-        to break backwards compatibility anyway we took the opportunity to fix all 3 issues at once.
         """)
         subparser = subparsers.add_parser('rcreate', parents=[common_parser], add_help=False,
                                           description=self.do_rcreate.__doc__, epilog=rcreate_epilog,
@@ -4418,8 +4402,6 @@ class Archiver:
                                help='Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.')
         subparser.add_argument('--make-parent-dirs', dest='make_parent_dirs', action='store_true',
                                help='create the parent directories of the repository directory, if they are missing.')
-        subparser.add_argument('--key-algorithm', dest='key_algorithm', default='argon2', choices=list(KEY_ALGORITHMS),
-                               help='the algorithm we use to derive a key encryption key from your passphrase. Default: argon2')
 
         # borg key
         subparser = subparsers.add_parser('key', parents=[mid_common_parser], add_help=False,
@@ -4544,46 +4526,6 @@ class Archiver:
         subparser.add_argument('--keep', dest='keep', action='store_true',
                                help='keep the key also at the current location (default: remove it)')
 
-        change_algorithm_epilog = process_epilog("""
-        Change the algorithm we use to encrypt and authenticate the borg key.
-
-        Important: In a `repokey` mode (e.g. repokey-blake2) all users share the same key.
-        In this mode upgrading to `argon2` will make it impossible to access the repo for users who use an old version of borg.
-        We recommend upgrading to the latest stable version.
-
-        Important: In a `keyfile` mode (e.g. keyfile-blake2) each user has their own key (in ``~/.config/borg/keys``).
-        In this mode this command will only change the key used by the current user.
-        If you want to upgrade to `argon2` to strengthen security, you will have to upgrade each user's key individually.
-
-        Your repository is encrypted and authenticated with a key that is randomly generated by ``borg init``.
-        The key is encrypted and authenticated with your passphrase.
-
-        We currently support two choices:
-
-        1. argon2 - recommended. This algorithm is used by default when initialising a new repository.
-           The key encryption key is derived from your passphrase via argon2-id.
-           Argon2 is considered more modern and secure than pbkdf2.
-        2. pbkdf2 - the legacy algorithm. Use this if you want to access your repo via old versions of borg.
-           The key encryption key is derived from your passphrase via PBKDF2-HMAC-SHA256.
-
-        Examples::
-
-            # Upgrade an existing key to argon2
-            borg key change-algorithm /path/to/repo argon2
-            # Downgrade to pbkdf2 - use this if upgrading borg is not an option
-            borg key change-algorithm /path/to/repo pbkdf2
-
-
-        """)
-        subparser = key_parsers.add_parser('change-algorithm', parents=[common_parser], add_help=False,
-                                           description=self.do_change_algorithm.__doc__,
-                                           epilog=change_algorithm_epilog,
-                                           formatter_class=argparse.RawDescriptionHelpFormatter,
-                                           help='change key algorithm')
-        subparser.set_defaults(func=self.do_change_algorithm)
-        subparser.add_argument('algorithm', metavar='ALGORITHM', choices=list(KEY_ALGORITHMS),
-                               help='select key algorithm')
-
         # borg list
         list_epilog = process_epilog("""
         This command lists the contents of an archive.

+ 1 - 1
src/borg/crypto/key.py

@@ -620,7 +620,7 @@ class FlexiKey:
             passphrase = Passphrase.new(allow_empty=True)
         key.init_ciphers()
         target = key.get_new_target(args)
-        key.save(target, passphrase, create=True, algorithm=KEY_ALGORITHMS[args.key_algorithm])
+        key.save(target, passphrase, create=True, algorithm=KEY_ALGORITHMS['argon2'])
         logger.info('Key in "%s" created.' % target)
         logger.info('Keep this key safe. Your data will be inaccessible without it.')
         return key

+ 1 - 1
src/borg/crypto/low_level.pyx

@@ -613,7 +613,7 @@ cdef class CHACHA20_POLY1305(_AEAD_BASE):
         super().__init__(key, iv=iv, header_len=header_len, aad_offset=aad_offset)
 
 
-cdef class AES:
+cdef class AES:  # legacy
     """A thin wrapper around the OpenSSL EVP cipher API - for legacy code, like key file encryption"""
     cdef CIPHER cipher
     cdef EVP_CIPHER_CTX *ctx

+ 6 - 35
src/borg/testsuite/archiver.py

@@ -3472,53 +3472,24 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
             key = msgpack.unpackb(a2b_base64(repository.load_key()))
         assert key['algorithm'] == 'argon2 chacha20-poly1305'
 
-    def test_init_with_explicit_key_algorithm(self):
-        """https://github.com/borgbackup/borg/issues/747#issuecomment-1076160401"""
-        self.cmd(f'--repo={self.repository_location}', 'rcreate', RK_ENCRYPTION, '--key-algorithm=pbkdf2')
-        with Repository(self.repository_path) as repository:
-            key = msgpack.unpackb(a2b_base64(repository.load_key()))
-        assert key['algorithm'] == 'sha256'
-
-    def verify_change_passphrase_does_not_change_algorithm(self, given_algorithm, expected_algorithm):
-        self.cmd(f'--repo={self.repository_location}', 'rcreate', RK_ENCRYPTION, '--key-algorithm', given_algorithm)
+    def test_change_passphrase_does_not_change_algorithm_argon2(self):
+        self.cmd(f'--repo={self.repository_location}', 'rcreate', RK_ENCRYPTION)
         os.environ['BORG_NEW_PASSPHRASE'] = 'newpassphrase'
 
         self.cmd(f'--repo={self.repository_location}', 'key', 'change-passphrase')
 
         with Repository(self.repository_path) as repository:
             key = msgpack.unpackb(a2b_base64(repository.load_key()))
-            assert key['algorithm'] == expected_algorithm
-
-    def test_change_passphrase_does_not_change_algorithm_argon2(self):
-        self.verify_change_passphrase_does_not_change_algorithm('argon2', 'argon2 chacha20-poly1305')
+            assert key['algorithm'] == 'argon2 chacha20-poly1305'
 
-    def test_change_passphrase_does_not_change_algorithm_pbkdf2(self):
-        self.verify_change_passphrase_does_not_change_algorithm('pbkdf2', 'sha256')
-
-    def verify_change_location_does_not_change_algorithm(self, given_algorithm, expected_algorithm):
-        self.cmd(f'--repo={self.repository_location}', 'rcreate', KF_ENCRYPTION, '--key-algorithm', given_algorithm)
+    def test_change_location_does_not_change_algorithm_argon2(self):
+        self.cmd(f'--repo={self.repository_location}', 'rcreate', KF_ENCRYPTION)
 
         self.cmd(f'--repo={self.repository_location}', 'key', 'change-location', 'repokey')
 
         with Repository(self.repository_path) as repository:
             key = msgpack.unpackb(a2b_base64(repository.load_key()))
-            assert key['algorithm'] == expected_algorithm
-
-    def test_change_location_does_not_change_algorithm_argon2(self):
-        self.verify_change_location_does_not_change_algorithm('argon2', 'argon2 chacha20-poly1305')
-
-    def test_change_location_does_not_change_algorithm_pbkdf2(self):
-        self.verify_change_location_does_not_change_algorithm('pbkdf2', 'sha256')
-
-    def test_key_change_algorithm(self):
-        self.cmd(f'--repo={self.repository_location}', 'rcreate', RK_ENCRYPTION, '--key-algorithm=pbkdf2')
-
-        self.cmd(f'--repo={self.repository_location}', 'key', 'change-algorithm', 'argon2')
-
-        with Repository(self.repository_path) as repository:
-            _, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
-        assert key._encrypted_key_algorithm == 'argon2 chacha20-poly1305'
-        self.cmd(f'--repo={self.repository_location}', 'rinfo')
+            assert key['algorithm'] == 'argon2 chacha20-poly1305'
 
 
 @unittest.skipUnless('binary' in BORG_EXES, 'no borg.exe available')

+ 3 - 4
src/borg/testsuite/key.py

@@ -396,8 +396,7 @@ def test_decrypt_key_file_v2_is_unsupported():
         key.decrypt_key_file(encrypted, "hello, pass phrase")
 
 
-@pytest.mark.parametrize('cli_argument, expected_algorithm', KEY_ALGORITHMS.items())
-def test_key_file_roundtrip(monkeypatch, cli_argument, expected_algorithm):
+def test_key_file_roundtrip(monkeypatch):
     def to_dict(key):
         extract = 'repository_id', 'enc_key', 'enc_hmac_key', 'id_key', 'chunk_seed'
         return {a: getattr(key, a) for a in extract}
@@ -405,10 +404,10 @@ def test_key_file_roundtrip(monkeypatch, cli_argument, expected_algorithm):
     repository = MagicMock(id=b'repository_id')
     monkeypatch.setenv('BORG_PASSPHRASE', "hello, pass phrase")
 
-    save_me = AESOCBRepoKey.create(repository, args=MagicMock(key_algorithm=cli_argument))
+    save_me = AESOCBRepoKey.create(repository, args=MagicMock(key_algorithm='argon2'))
     saved = repository.save_key.call_args.args[0]
     repository.load_key.return_value = saved
     load_me = AESOCBRepoKey.detect(repository, manifest_data=None)
 
     assert to_dict(load_me) == to_dict(save_me)
-    assert msgpack.unpackb(a2b_base64(saved))['algorithm'] == expected_algorithm
+    assert msgpack.unpackb(a2b_base64(saved))['algorithm'] == KEY_ALGORITHMS['argon2']