5Xc@sdZddlmZmZddlZejeZddlm Z ddl m Z m Z ddlm Z mZmZddlmZmZmZddlmZddljjZd gZed Zed Zed Zd ejej ej!ej"ej#ej$fd YZ dS(s/passlib.handlers.scrypt -- scrypt password hashi(twith_statementtabsolute_importN(tscrypt(th64tto_bytes(Rt b64s_decodet b64s_encode(tut bascii_to_strtsuppress_cause(t classpropertyRs$scrypt$s$7$t$cBs7eZdZdZdZdZeZeefZ d Z d Z d Z d Z d Zd Zd ZdZed dZedZedZedZedZdZd dZeedZdZedZedZ eddZ!ededZ"dZ#dZ$RS(!s 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. Rtidenttsaltt salt_sizetroundst block_sizet parallelismi iiiitlog2icKstt|j|}|dk rit|tjrEt|}n|j|d|j d|_ ny$t j d|j >|j |jWn/tk r}ttdt|nX|S(Ntrelaxedis&scrypt: invalid settings combination: (tsuperRtusingtNonet isinstancetuhtnative_string_typestintt_norm_block_sizetgetRt_scrypttvalidatetdefault_roundsRt ValueErrorR tstr(tclsRtkwdstsubclsterr((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRs $$ cCs||j|S(N(tparse(R"thash((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt from_stringscCsZ|j|\}}t|d|jtd}|rD||Stjj|dS(Ns_parse_%s_string(t _parse_identtgetattrtstript_UDOLLARRRtexctInvalidHashError(R"R'R tsuffixtfunc((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR&s  c Csi|jd}t|dkr3|\}}}n<t|dkrZ|\}}d}ntjj|d|jd}t|dkr|\}}}|jdst|jdst|jdstntjj|d td t d t |dd t |dd t |ddt |j dd|rbt |j dndS(NR iismalformed hasht,sln=sr=sp=smalformed settings fieldR RRRR tasciitchecksum( tsplittlenRRR-tMalformedHashErrort startswithtAssertionErrortdictt IDENT_SCRYPTRRtencode( R"R/tpartstparamsR tdigesttnstrtbstrtpstr((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_parse_scrypt_strings*  cCs|jdjd}t|dkr9|\}}n3t|dkr]|\}d}ntjjt|dkrtjj|dntdtdt j |d d t j |dd !d t j |d d!d |dd |rt j |ndS(NR2R iii sparams field too shortR RRiRR R3( R;R4R5RRR-R6R9tIDENT_7Rt decode_int6t decode_int30t decode_bytes(R"R/R<R=R>((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_parse_7_strings    c Cs|j}|tkrSd|j|j|jtt|jtt|jfS|t kset |j}y|j dWn#t k rt tdnXtdjdtj|jtj|jtj|j|jdtj|jgSdS(Ns$scrypt$ln=%d,r=%d,p=%d$%s$%sR2s.scrypt $7$ hashes dont support non-ascii saltsts$7$R (R R:RRRRRR R3RCR8tdecodetUnicodeDecodeErrorR tNotImplementedErrortjoinRt encode_int6t encode_int30t encode_bytes(tselfR R ((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt to_strings,     cKsbtt|j||dkrLtj||j|jdds^tn|j||_dS(NtparamR( RRt__init__RRtvalidate_default_valueRRR8(RPRR#((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRS1s  c Cs"tj||ddddd|S(NtminiRRRR(Rt norm_integer(R"RR((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR>scCs7tt|j}|jtkr3t|}n|S(N(RRt_generate_saltR RCR(RPR ((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRWBscCstjS(N(Rtbackend_values(R"((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pytbackendsPscCstjS(N(Rtbackend(R"((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt get_backendTstanycCs:y|j|dttSWntjjk r5tSXdS(Ntdryrun(t set_backendtTrueRR-tMissingBackendErrortFalse(R"tname((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt has_backendXs cCstj|d|dS(NR](Rt _set_backend(R"RbR]((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR^`sc CsMt|dd}tj||jdd|j>d|jd|jd|jS(NRRtsecrettnitrtptkeylen(RRRR RRRt checksum_size(RPRe((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_calc_checksumgs(cKs2|jt|jkrtStt|j|S(sR mark hash as needing update if rounds is outside desired bounds. (RttypeR_RRt_calc_needs_update(RPR#((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRmps(sidentssaltRsroundss block_sizes parallelismN(%t__name__t __module__t__doc__Rbt setting_kwdsRjR:t default_identRCt ident_valuestdefault_salt_sizet max_salt_sizeRt min_roundst max_roundst rounds_costRRt classmethodRRR(R&RBRGRQRSRaRRWR RYR[RcR^RkRm(((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR!sB@    .    (%Rpt __future__RRtloggingt getLoggerRntlogtpasslib.cryptoRRt passlib.utilsRRtpasslib.utils.binaryRRtpasslib.utils.compatRRR tpasslib.utils.decorR tpasslib.utils.handlerstutilsthandlersRt__all__R:RCR,tParallelismMixint HasRoundst HasRawSalttHasRawChecksumt HasManyIdentstGenericHandler(((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyts     !