a fWcB7 @sdZddlmZmZddlZeeZddlm Z ddl m Z m Z ddlm Z mZmZddlmZmZmZddlmZddlmmZd gZed Zed Zed ZGd d d ejej ej!ej"ej#ej$Z dS)z/passlib.handlers.scrypt -- scrypt password hash)with_statementabsolute_importN)scrypt)h64to_bytes)r b64s_decode b64s_encode)u bascii_to_strsuppress_cause) classpropertyrz$scrypt$z$7$$cseZdZdZdZdZdZeZee fZ dZ dZ dZ dZdZdZdZd Zed+fd d Zed dZeddZeddZeddZddZd,fdd Zed-ddZfddZeddZed d!Zed.d#d$Z ed/d%d&Z!d'd(Z"fd)d*Z#Z$S)0ra This class implements an SCrypt-based password [#scrypt-home]_ hash, and follows the :ref:`password-hash-api`. It supports a variable-length salt, a variable number of rounds, as well as some custom tuning parameters unique to scrypt (see below). The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords: :type salt: str :param salt: Optional salt string. If specified, the length must be between 0-1024 bytes. If not specified, one will be auto-generated (this is recommended). :type salt_size: int :param salt_size: Optional number of bytes to use when autogenerating new salts. Defaults to 16 bytes, but can be any value between 0 and 1024. :type rounds: int :param rounds: Optional number of rounds to use. Defaults to 16, but must be within ``range(1,32)``. .. warning:: Unlike many hash algorithms, increasing the rounds value will increase both the time *and memory* required to hash a password. :type block_size: int :param block_size: Optional block size to pass to scrypt hash function (the ``r`` parameter). Useful for tuning scrypt to optimal performance for your CPU architecture. Defaults to 8. :type parallelism: int :param parallelism: Optional parallelism to pass to scrypt hash function (the ``p`` parameter). Defaults to 1. :type relaxed: bool :param relaxed: By default, providing an invalid value for one of the other keywords will result in a :exc:`ValueError`. If ``relaxed=True``, and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning` will be issued instead. Correctable errors include ``rounds`` that are too small or too large, and ``salt`` strings that are too long. .. note:: The underlying scrypt hash function has a number of limitations on it's parameter values, which forbids certain combinations of settings. The requirements are: * ``linear_rounds = 2**`` * ``linear_rounds < 2**(16 * block_size)`` * ``block_size * parallelism <= 2**30-1`` .. todo:: This class currently does not support configuring default values for ``block_size`` or ``parallelism`` via a :class:`~passlib.context.CryptContext` configuration. )identsaltZ salt_sizerounds block_size parallelism iZlog2Nc stt|jfi|}|durHt|tjr2t|}|j||dd|_ zt d|j >|j |j Wn8ty}z ttdt|WYd}~n d}~00|S)Nrelaxed)rrz&scrypt: invalid settings combination: )superrusing isinstanceuhZnative_string_typesint_norm_block_sizegetr_scryptZvalidatedefault_roundsr ValueErrorr str)clsrkwdssubclserr __class__;/usr/lib/python3.9/site-packages/passlib/handlers/scrypt.pyrs *z scrypt.usingcCs|fi||SN)parse)r$hashr*r*r+ from_stringszscrypt.from_stringcCs@||\}}t|d|td}|r0||Stj|dS)Nz_parse_%s_string)Z _parse_identgetattrstrip_UDOLLARrexcZInvalidHashError)r$r.rsuffixfuncr*r*r+r-s z scrypt.parsec Cs|d}t|dkr"|\}}}n(t|dkr<|\}}d}ntj|d|d}t|dkr|\}}}|dsxJ|dsJ|dsJntj|d ttt|ddt|ddt|ddt | d |rt | d ndd S) Nr zmalformed hash,zln=zr=zp=zmalformed settings fieldasciirrrrrchecksum) splitlenrr3MalformedHashError startswithdict IDENT_SCRYPTrrencode) r$r4partsparamsrdigestZnstrZbstrZpstrr*r*r+_parse_scrypt_strings,        zscrypt._parse_scrypt_stringc Cs|dd}t|dkr&|\}}n"t|dkr>|\}d}n tjt|dkrbtj|dttt |ddt |ddt |dd|dd|rt |nddS) Nr9$r7r zparams field too shortr:) rBr<r=rr3r>r@IDENT_7rZ decode_int6Z decode_int30Z decode_bytes)r$r4rCrDrEr*r*r+_parse_7_strings"      zscrypt._parse_7_stringc Cs|j}|tkr:d|j|j|jtt|jtt|jfS|t ksFJ|j}z| dWnt yxt t dYn0tddt|jt|jt|j|jdt|jgSdS)Nz$scrypt$ln=%d,r=%d,p=%d$%s$%sr9z.scrypt $7$ hashes dont support non-ascii saltss$7$rG)rrArrrr rrr;rJdecodeUnicodeDecodeErrorr NotImplementedErrorjoinrZ encode_int6Z encode_int30Z encode_bytes)selfrrr*r*r+ to_strings0        zscrypt.to_stringc sJtt|jfi||dur:tj||j|jddsFJn |||_dS)Nrparam)rr__init__rZvalidate_default_valuerr)rQrr%r(r*r+rU1s  zscrypt.__init__FcCstj||dd|dS)Nrr)minrTr)rZ norm_integer)r$rrr*r*r+r>szscrypt._norm_block_sizecs$tt|}|jtkr t|}|Sr,)rr_generate_saltrrJr)rQrr(r*r+rWBs zscrypt._generate_saltcCstjSr,)r Zbackend_valuesr$r*r*r+backendsPszscrypt.backendscCstjSr,)r ZbackendrXr*r*r+ get_backendTszscrypt.get_backendanycCs2z|j|ddWdStjjy,YdS0dS)NTdryrunF) set_backendrr3ZMissingBackendError)r$namer*r*r+ has_backendXs zscrypt.has_backendcCstj||ddS)Nr\)r Z _set_backend)r$r_r]r*r*r+r^`szscrypt.set_backendcCs0t|dd}tj||jd|j>|j|j|jdS)NsecretrSr)nrpZkeylen)rr rrrrr checksum_size)rQrar*r*r+_calc_checksumgs zscrypt._calc_checksumc s*|jt|jkrdStt|jfi|S)zR mark hash as needing update if rounds is outside desired bounds. T)rtyperr_calc_needs_update)rQr%r(r*r+rhpszscrypt._calc_needs_update)N)N)F)r[)r[F)%__name__ __module__ __qualname____doc__r_Z setting_kwdsrerAZ default_identrJZ ident_valuesZdefault_salt_sizeZ max_salt_sizer!Z min_roundsZ max_roundsZ rounds_costrr classmethodrr/r-rFrKrRrUrrWr rYrZr`r^rfrh __classcell__r*r*r(r+r!sNG     -         )%rlZ __future__rrZloggingZ getLoggerrilogZpasslib.cryptorr Z passlib.utilsrrZpasslib.utils.binaryrrZpasslib.utils.compatr r r Zpasslib.utils.decorr Zpasslib.utils.handlersZutilshandlersr__all__rArJr2ZParallelismMixinZ HasRoundsZ HasRawSaltZHasRawChecksumZ HasManyIdentsZGenericHandlerr*r*r*r+s