Passphrase.argon2 -> FlexiKey.argon2

This commit is contained in:
Andrey Bienkowski 2022-04-10 15:06:26 +03:00
parent 0850a7c295
commit fc6d423052
4 changed files with 41 additions and 39 deletions

View File

@ -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")

View File

@ -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,

View File

@ -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

View File

@ -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)