瀏覽代碼

Passphrase.argon2 -> FlexiKey.argon2

Andrey Bienkowski 3 年之前
父節點
當前提交
fc6d423052
共有 4 個文件被更改,包括 41 次插入39 次删除
  1. 2 3
      src/borg/archiver.py
  2. 38 2
      src/borg/crypto/key.py
  3. 0 33
      src/borg/helpers/passphrase.py
  4. 1 1
      src/borg/testsuite/crypto.py

+ 2 - 3
src/borg/archiver.py

@@ -622,12 +622,11 @@ class Archiver:
         for spec, func in tests:
             print(f"{spec:<24} {size:<10} {timeit(func, number=100):.3f}s")
 
-        from borg.helpers.passphrase import Passphrase
         print("KDFs (slow is GOOD, use argon2!) ===============================")
         count = 5
         for spec, func in [
-            ("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)),
+            ("pbkdf2", lambda: FlexiKey.pbkdf2('mypassphrase', b'salt'*8, PBKDF2_ITERATIONS, 32)),
+            ("argon2", lambda: FlexiKey.argon2('mypassphrase', 64, b'S' * ARGON2_SALT_BYTES, **ARGON2_ARGS)),
         ]:
             print(f"{spec:<24} {count:<10} {timeit(func, number=count):.3f}s")
 

+ 38 - 2
src/borg/crypto/key.py

@@ -4,11 +4,14 @@ import os
 import textwrap
 from binascii import a2b_base64, b2a_base64, hexlify
 from hashlib import sha256, pbkdf2_hmac
+from typing import Literal
 
 from ..logger import create_logger
 
 logger = create_logger()
 
+import argon2.low_level
+
 from ..constants import *  # NOQA
 from ..compress import Compressor
 from ..helpers import StableDict
@@ -453,6 +456,37 @@ class FlexiKey:
             iterations = 1
         return pbkdf2_hmac('sha256', passphrase.encode('utf-8'), salt, iterations, output_len_in_bytes)
 
+    @staticmethod
+    def argon2(
+        passphrase,
+        output_len_in_bytes: int,
+        salt: bytes,
+        time_cost,
+        memory_cost,
+        parallelism,
+        type: Literal['i', 'd', 'id']
+    ) -> bytes:
+        if os.environ.get("BORG_TESTONLY_WEAKEN_KDF") == "1":
+            time_cost = 1
+            parallelism = 1
+            # 8 is the smallest value that avoids the "Memory cost is too small" exception
+            memory_cost = 8
+        type_map = {
+            'i': argon2.low_level.Type.I,
+            'd': argon2.low_level.Type.D,
+            'id': argon2.low_level.Type.ID,
+        }
+        key = argon2.low_level.hash_secret_raw(
+            secret=passphrase.encode("utf-8"),
+            hash_len=output_len_in_bytes,
+            salt=salt,
+            time_cost=time_cost,
+            memory_cost=memory_cost,
+            parallelism=parallelism,
+            type=type_map[type],
+        )
+        return key
+
     def decrypt_key_file_pbkdf2(self, encrypted_key, passphrase):
         key = self.pbkdf2(passphrase, encrypted_key.salt, encrypted_key.iterations, 32)
         data = AES(key, b'\0'*16).decrypt(encrypted_key.data)
@@ -461,7 +495,8 @@ class FlexiKey:
         return None
 
     def decrypt_key_file_argon2(self, encrypted_key, passphrase):
-        key = passphrase.argon2(
+        key = self.argon2(
+            passphrase,
             output_len_in_bytes=64,
             salt=encrypted_key.salt,
             time_cost=encrypted_key.argon2_time_cost,
@@ -506,7 +541,8 @@ class FlexiKey:
 
     def encrypt_key_file_argon2(self, data, passphrase):
         salt = os.urandom(ARGON2_SALT_BYTES)
-        key = passphrase.argon2(
+        key = self.argon2(
+            passphrase,
             output_len_in_bytes=64,
             salt=salt,
             **ARGON2_ARGS,

+ 0 - 33
src/borg/helpers/passphrase.py

@@ -3,7 +3,6 @@ import os
 import shlex
 import subprocess
 import sys
-from typing import Literal
 
 from . import bin_to_hex
 from . import Error
@@ -12,8 +11,6 @@ from . import prepare_subprocess_env
 
 from ..logger import create_logger
 
-import argon2.low_level
-
 logger = create_logger()
 
 
@@ -138,33 +135,3 @@ class Passphrase(str):
 
     def __repr__(self):
         return '<Passphrase "***hidden***">'
-
-    def argon2(
-        self,
-        output_len_in_bytes: int,
-        salt: bytes,
-        time_cost,
-        memory_cost,
-        parallelism,
-        type: Literal['i', 'd', 'id']
-    ) -> bytes:
-        if os.environ.get("BORG_TESTONLY_WEAKEN_KDF") == "1":
-            time_cost = 1
-            parallelism = 1
-            # 8 is the smallest value that avoids the "Memory cost is too small" exception
-            memory_cost = 8
-        type_map = {
-            'i': argon2.low_level.Type.I,
-            'd': argon2.low_level.Type.D,
-            'id': argon2.low_level.Type.ID,
-        }
-        key = argon2.low_level.hash_secret_raw(
-            secret=self.encode("utf-8"),
-            hash_len=output_len_in_bytes,
-            salt=salt,
-            time_cost=time_cost,
-            memory_cost=memory_cost,
-            parallelism=parallelism,
-            type=type_map[type],
-        )
-        return key

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

@@ -294,7 +294,7 @@ 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
-    passphrase = Passphrase("hello, pass phrase")
+    passphrase = "hello, pass phrase"
     key = FlexiKey.pbkdf2(passphrase, salt, 1, 32)
     hash = hmac_sha256(key, plain)
     data = AES(key, b'\0'*16).encrypt(plain)