�
�
5Xc@�sdZddlmZmZddlZeje�Zddlm Z
ddlmZm
Z
ddlmZmZmZddlmZmZmZddlmZddljjZd 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(Rtb64s_decodetb64s_encode(tut
bascii_to_strtsuppress_cause(t
classpropertyRs$scrypt$s$7$t$cB�s7eZdZdZdZdZeZeefZ d Z
d
Zd ZdZ
dZd
ZdZdZed d��Zed��Zed��Zed��Zed��Zd�Zd d�Zeed��Zd�Zed��Zed��Z edd��Z!eded��Z"d�Z#d�Z$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**<some positive integer>``
* ``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_sizetparallelismi iiiitlog2icK�s�tt|�j|�}|dk rit|tj�rEt|�}n|j|d|j d��|_
ny$tjd|j
>|j
|j�Wn/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.pyR�s$$ cC�s||j|��S(N(tparse(R"thash((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pytfrom_string�scC�sZ|j|�\}}t|d|jt�d�}|rD||�Stjj|��dS(Ns_parse_%s_string(t_parse_identtgetattrtstript_UDOLLARRRtexctInvalidHashError(R"R'Rtsuffixtfunc((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR&�s
c C�s*|jd�}t|�dkr3|\}}}n<t|�dkrZ|\}}d}ntjj|d��|jd�}t|�dkr�|\}}}ntjj|d��tdtdt|d�d t|d�d
t|d�dt |j
d��d
|r#t |j
d��nd�S(NRiismalformed hasht,smalformed settings fieldRRRRR
tasciitchecksum(tsplittlenRRR-tMalformedHashErrortdicttIDENT_SCRYPTRRtencode( R"R/tpartstparamsR
tdigesttnstrtbstrtpstr((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_parse_scrypt_string�s& cC�s|jd�jd�}t|�dkr9|\}}n3t|�dkr]|\}d}ntjj��t|�dkr�tjj|d��ntdtdt j
|d �d t j|dd
!�dt j|d
d!�d|dd
|rt j|�nd�S(NR2Riiisparams field too shortRRRiRR
R3(
R9R4R5RRR-R6R7tIDENT_7Rtdecode_int6tdecode_int30tdecode_bytes(R"R/R:R;R<((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_parse_7_string�s
c
C�s�|j}|tkrSd|j|j|jtt|j��tt|j��fS|j}y|j d�Wn#t
k
r�ttd���nXtdj
dtj|j�tj|j�tj|j�|jdtj|j�g��SdS(Ns$scrypt$ln=%d,r=%d,p=%d$%s$%sR2s.scrypt $7$ hashes dont support non-ascii saltsts$7$R(RR8RRRRRR
R3tdecodetUnicodeDecodeErrorR tNotImplementedErrortjoinRtencode_int6tencode_int30tencode_bytes(tselfRR
((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt to_strings*
cK�s;tt|�j|�|dkr%n|j|�|_dS(N(RRt__init__RRR(RNRR#((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRP1sc C�s"tj||ddddd|�S(NtminitparamRR(Rtnorm_integer(R"RR((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR>scC�s7tt|�j�}|jtkr3t|�}n|S(N(RRt_generate_saltRRAR(RNR
((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRTBscC�stjS(N(Rtbackend_values(R"((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pytbackendsPscC�stjS(N(Rtbackend(R"((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pytget_backendTstanycC�s:y|j|dt�tSWntjjk
r5tSXdS(Ntdryrun(tset_backendtTrueRR-tMissingBackendErrortFalse(R"tname((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pythas_backendXs
cC�stj|d|�dS(NRZ(Rt_set_backend(R"R_RZ((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR[`scC�sMt|dd�}tj||jdd|j>d|jd|jd|j�S(NRRtsecrettnitrtptkeylen(RRRR
RRRt
checksum_size(RNRb((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt_calc_checksumgs(cK�s2|jt|�jkrtStt|�j|�S(sR
mark hash as needing update if rounds is outside desired bounds.
(RttypeR\RRt_calc_needs_update(RNR#((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyRjps(sidentssaltRsroundss
block_sizesparallelismN(%t__name__t
__module__t__doc__R_tsetting_kwdsRgR8t
default_identRAtident_valuestdefault_salt_sizet
max_salt_sizeRt
min_roundst
max_roundstrounds_costRRtclassmethodRRR(R&R@RERORPR^RRTR
RVRXR`R[RhRj(((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyR!sB@ .
(%Rmt
__future__RRtloggingt getLoggerRktlogtpasslib.cryptoRRt
passlib.utilsRRtpasslib.utils.binaryRRtpasslib.utils.compatRRR tpasslib.utils.decorR
tpasslib.utils.handlerstutilsthandlersRt__all__R8RAR,tParallelismMixint HasRoundst
HasRawSalttHasRawChecksumt
HasManyIdentstGenericHandler(((s;/usr/lib/python2.7/site-packages/passlib/handlers/scrypt.pyt<module>s ! |