mirror of https://github.com/borgbackup/borg.git
Passphrase.argon2 -> FlexiKey.argon2
This commit is contained in:
parent
0850a7c295
commit
fc6d423052
|
@ -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")
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue