Răsfoiți Sursa

Argon2 the third part: `borg key change-algorithm` (#6549)

add `borg key change-algorithm` to change the kdf / key processing
Andrey Andreyevich Bienkowski 3 ani în urmă
părinte
comite
d386b0346d
2 a modificat fișierele cu 43 adăugiri și 0 ștergeri
  1. 33 0
      src/borg/archiver.py
  2. 10 0
      src/borg/testsuite/archiver.py

+ 33 - 0
src/borg/archiver.py

@@ -421,6 +421,15 @@ class Archiver:
 
         return EXIT_SUCCESS
 
+    @with_repository(exclusive=True, compatibility=(Manifest.Operation.CHECK,))
+    def do_change_algorithm(self, args, repository, manifest, key):
+        """Change repository key algorithm"""
+        if not hasattr(key, 'change_passphrase'):
+            print('This repository is not encrypted, cannot change the algorithm.')
+            return EXIT_ERROR
+        key.save(key.target, key._passphrase, algorithm=KEY_ALGORITHMS[args.algorithm])
+        return EXIT_SUCCESS
+
     @with_repository(lock=False, exclusive=False, manifest=False, cache=False)
     def do_key_export(self, args, repository):
         """Export the repository key for backup"""
@@ -4455,6 +4464,30 @@ 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.
+
+        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.
+        1. 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.
+        """)
+        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('location', metavar='REPOSITORY', nargs='?', default='',
+                               type=location_validator(archive=False))
+        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 a repository or an archive.

+ 10 - 0
src/borg/testsuite/archiver.py

@@ -3630,6 +3630,16 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
     def test_change_location_does_not_change_algorithm_pbkdf2(self):
         self.verify_change_location_does_not_change_algorithm('pbkdf2', b'sha256')
 
+    def test_key_change_algorithm(self):
+        self.cmd('init', '--encryption=repokey', '--key-algorithm=pbkdf2', self.repository_location)
+
+        self.cmd('key', 'change-algorithm', self.repository_location, 'argon2')
+
+        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'
+        self.cmd('info', self.repository_location)
+
 
 @unittest.skipUnless('binary' in BORG_EXES, 'no borg.exe available')
 class ArchiverTestCaseBinary(ArchiverTestCase):