From: Philipp Gesang Date: Mon, 20 Mar 2017 16:35:45 +0000 (+0100) Subject: implement null-kdf to speed up testing X-Git-Tag: v2.2~7^2~221 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=c46c867055e6833329eb420c188a54e7c728ddf6;p=python-delta-tar implement null-kdf to speed up testing With “parameter version” zero, the KDF consists only of a trivial string derived from the password so as to reduce runtime. (SCRYPT takes about 48 seconds here with our parameters.) --- diff --git a/deltatar/crypto.py b/deltatar/crypto.py index 17466ad..1dab1be 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -32,7 +32,7 @@ passed in advance: https://github.com/pyca/cryptography/pull/3421 import binascii import ctypes import io -from functools import reduce +from functools import reduce, partial import os import struct import sys @@ -61,7 +61,9 @@ __all__ = [ "hdr_make", "hdr_read", "hdr_fmt", "hdr_fmt_pretty" ############################################################################### ENCRYPTION_PARAMETERS = \ - { 1: \ + { 0: \ + { "kdf": ("dummy", 16) } + , 1: \ { "kdf": ("scrypt", { "dkLen" : 16 , "N" : 1 << 15 @@ -113,13 +115,6 @@ AES_GCM_IV_LEN = 12 AES_GCM_MAX_SIZE = (1 << 36) - (1 << 5) # 2^39 - 2^8 b ≅ 64 GB AES_GCM_FMT_TAG = "<16s" -# scrypt -SCRYPT_dkLen = 16 -SCRYPT_N = 1 << 15 -SCRYPT_r = 8 -SCRYPT_p = 1 -SCRYPT_NaCl_LEN = 16 - ############################################################################### ## header, trailer @@ -262,7 +257,32 @@ def tag_read_stream (source): ## convenience wrapper ############################################################################### -KEY_MEMO = { } # static because needed for both the info file and the archive + +def kdf_dummy (klen, password, _nacl): + q, r = divmod (klen, len (password)) + if isinstance (password, bytes) is False: + password = password.encode () + return password * q + password [:r], b"" + + +SCRYPT_KEY_MEMO = { } # static because needed for both the info file and the archive + + +def kdf_scrypt (params, password, nacl): + N = params["N"] + r = params["r"] + p = params["p"] + dkLen = params["dkLen"] + + if nacl is None: + nacl = os.urandom (params["NaCl_LEN"]) + + key_parms = (password, nacl, N, r, p, dkLen) + global SCRYPT_KEY_MEMO + if key_parms not in SCRYPT_KEY_MEMO: + SCRYPT_KEY_MEMO [key_parms] = \ + pylibscrypt.scrypt (password, nacl, N, r, p, dkLen) + return SCRYPT_KEY_MEMO [key_parms], nacl def kdf_by_version (paramversion): @@ -271,9 +291,12 @@ def kdf_by_version (paramversion): raise ValueError ("no encryption parameters for version %r" % paramversion) (kdf, params) = defs["kdf"] - if kdf != "scrypt": + fn = None + if kdf == "scrypt" : fn = kdf_scrypt + if kdf == "dummy" : fn = kdf_dummy + if fn is None: raise ValueError ("key derivation method %r unknown" % kdf) - return kdf, params + return partial (fn, params) @@ -293,23 +316,14 @@ class Crypto (object): self.set_parameters (*al, **akv) - def set_parameters (self, password, paramversion, nacl, pfx=None): + def set_parameters (self, password, paramversion, nacl=None, pfx=None): if isinstance (password, bytes) is False: password = str.encode (password) self.password = password self.nacl = nacl self.paramversion = paramversion - (kdf, params) = kdf_by_version (paramversion) - - N = params["N"] - r = params["r"] - p = params["p"] - dkLen = params["dkLen"] - - key_parms = (password, nacl, N, r, p, dkLen) - global KEY_MEMO - if key_parms not in KEY_MEMO: - KEY_MEMO [key_parms] = pylibscrypt.scrypt (password, nacl, N, r, p, dkLen) - self.key = KEY_MEMO [key_parms] + kdf = kdf_by_version (paramversion) + if kdf is not None: + self.key, self.nacl = kdf (password, nacl) if pfx is not None: self.pfx = pfx @@ -331,9 +345,6 @@ class Encrypt (Crypto): ctsize = -1 # per object from .next() → .done() def __init__ (self, password, paramversion, nacl=None): - if nacl is None: - _, params = kdf_by_version (paramversion) - nacl = os.urandom (params["NaCl_LEN"]) super().__init__ (password, paramversion, nacl) @@ -343,7 +354,7 @@ class Encrypt (Crypto): def next (self, filename, version, paramversion, nacl): self.iv = self.iv_make() - self.curobj = (filename, version, paramversion, nacl) + self.curobj = (filename, version, paramversion, nacl or self.nacl) self.cnt += 1 self.ctsize = 0 self.aes = Cipher \