Current File : //usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyo
�
��nXc@�s�dZddlmZmZddlmZddlmZddlZddl	Z	ddl
Z
e
je�Z
ddlmZeaeaeaeaddlmZmZmZddlmZmZmZmZmZmZm Z m!Z!dd	l"m#Z#dd
l$m%Z%m&Z&m'Z'm(Z(ddl)j*j+Z,dgZ-e%d�Z.e%d
�Z/e%d�Z0e%d�Z1e%d�Z2dZ3dZ4d�Z5de,j6e,j7e,j8e,j9e,j:e,j;fd��YZ<de<fd��YZ=de<fd��YZ>de<fd��YZ?de<fd��YZ@de<fd��YZAd e<fd!��YZBde=e<fd"��YZCe%d#�ZDd$eCfd%��YZEd&eEfd'��YZFdS((s�passlib.bcrypt -- implementation of OpenBSD's BCrypt algorithm.

TODO:

* support 2x and altered-2a hashes?
  http://www.openwall.com/lists/oss-security/2011/06/27/9

* deal with lack of PY3-compatibile c-ext implementation
i(twith_statementtabsolute_import(t	b64encode(tsha256N(twarn(tPasslibHashWarningtPasslibSecurityWarningtPasslibSecurityError(t
safe_cryptt
repeat_stringtto_bytest
parse_versiontrngt
getrandstrt
test_cryptt
to_unicode(tbcrypt64(tut
uascii_to_strtunicodet
str_to_uasciitbcrypts$2$s$2a$s$2x$s$2y$s$2b$ts<$2a$04$5BJqKfqMQvV7nS.yUguNcueVirQqDBGaLXSqj.rs.pZPlNR0UX/HKcC�sRyddl}Wntk
r$dSXyddlm}Wntk
rMtSXtS(s!
    internal helper which tries to distinguish pybcrypt vs bcrypt.

    :returns:
        True if cext-based py-bcrypt,
        False if ffi-based bcrypt,
        None if 'bcrypt' module not found.

    .. versionchanged:: 1.6.3

        Now assuming bcrypt installed, unless py-bcrypt explicitly detected.
        Previous releases assumed py-bcrypt by default.

        Making this change since py-bcrypt is (apparently) unmaintained and static,
        whereas bcrypt is being actively maintained, and it's internal structure may shift.
    iN(t__version__(RtImportErrortNonetbcrypt._bcryptRtFalsetTrue(RR((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt_detect_pybcrypt4s

t
_BcryptCommoncB�sleZdZdZdZdZejZe	Z
eee
ee	fZieed�6eed�6eed	�6e	ed
�6ZdZZejZdZd
ZdZdZdZeZeZeZeZeZeZ e!d��Z"d�Z#d�Z$e!d��Z%e!d��Z&e!d��Z'e!d��Z(ed�Z)dZ*e!d��Z+d�Z,e!ed��Z-RS(s&
    Base class which implements brunt of BCrypt code.
    This is then subclassed by the various backends,
    to override w/ backend-specific methods.

    When a backend is loaded, the bases of the 'bcrypt' class proper
    are modified to prepend the correct backend-specific subclass.
    Rtsalttroundstidentttruncate_errorit2t2at2yt2biiitlog2iHc	
C�s�|j|�\}}|tkr0td��n|jtd��\}}t|�}|td�|fkr�tjj|d��n|d |d}}|d|d|d|p�dd	|�S(
Ns>crypt_blowfish's buggy '2x' hashes are not currently supportedt$s%02dsmalformed cost fieldiR RtchecksumR!(
t_parse_identtIDENT_2Xt
ValueErrortsplitRtinttuhtexctMalformedHashErrorR(	tclsthashR!ttailt
rounds_strtdataR Rtchk((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytfrom_string�scC�s2td�|j|j|j|jf}t|�S(Ns%s%02d$%s%s(RR!R RR)R(tselfR3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt	to_string�s(cC�s)td�||j|jf}t|�S(s5internal helper to prepare config string for backendss	%s%02d$%s(RR RR(R9R!tconfig((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt_get_config�scK�sdt|t�r!|jd�}n|jt�rK|dtjdkrKtStt	|�j
||�S(Ntasciiii(t
isinstancetbytestdecodet
startswithtIDENT_2ARt	_padinfo2RtsuperRtneeds_update(R2R3tkwds((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRE�s
&cC�s*|j|�r"|j|�j�S|SdS(s<helper to normalize hash, correcting any bcrypt padding bitsN(tidentifyR8R:(R2R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytnormhash�scC�s"tt|�j�}tj|�S(N(RDRt_generate_saltRt
repair_unused(R2R((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRI�scK�sJtt|�j||�}tj|�\}}|rFtdt�n|S(Ns�encountered a bcrypt salt with incorrectly set padding bits; you may want to use bcrypt.normhash() to fix this; this will be an error under Passlib 2.0(RDRt
_norm_saltRtcheck_repair_unusedRR(R2RRFtchanged((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRK�s
cC�sMtt|�j|d|�}tj|�\}}|rItdt�n|S(Ntrelaxeds�encountered a bcrypt hash with incorrectly set padding bits; you may want to use bcrypt.normhash() to fix this; this will be an error under Passlib 2.0(RDRt_norm_checksumRRLRR(R9R)RNRM((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRO�s
s9 -- recommend you install one (e.g. 'pip install bcrypt')c
�s^|jr
tS|j�tf�tr;�tjjf7�n���fd�}��fd�}��fd����fd�}d}|d|�}|s�td���n(|tkr�t|_	t
jd��n|dt�}|std	���nX|tkr#td
���n9|t
��t
�r\td�tjj�t|_ntjdd
�}|d|�}|s�td���n<|tkr�t|_t
jd��n|t�|t�tjdd�}	|d|	�}|std���nE|tkr4t|_t
jd��nt|_|t�|t�t|_tS(s�
        helper called by from backend mixin classes' _load_backend_mixin() --
        invoked after backend imports have been loaded, and performs
        feature detection & testing common to all backends.
        c�sYy�||�SWnA�k
r%tStk
rT}tjd�||dt�tSXdS(s8verify() wrapper which traps 'unknown identifier' errorss<trapped unexpected response from %r backend: verify(%r, %r):texc_infoN(tNotImplementedtAssertionErrortlogtdebugR(tsecretR3terr(tbackendt	err_typestverify(s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytsafe_verify"s
	c�szd}|jd�d}�||�r;td���n|jd�d}�||�svtd�|f��ndS(s
            helper to check for cryptblowfish 8bit bug (fixed in 2y/2b);
            even though it's not known to be present in any of passlib's backends.
            this is treated as FATAL, because it can easily result in seriously malformed hashes,
            and we can't correct for it ourselves.

            test cases from <http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/glibc/crypt_blowfish/wrapper.c.diff?r1=1.9;r2=1.10>
            reference hash is the incorrectly generated $2x$ hash taken from above url
            s�R=s805$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3es�passlib.hash.bcrypt: Your installation of the %r backend is vulnerable to the crypt_blowfish 8-bit bug (CVE-2011-2483), and should be upgraded or replaced with another backend.s805$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCqs(%s backend failed to verify %s 8bit hashN(tencodeRtRuntimeError(R!RUtbug_hashtcorrect_hash(RWRY(s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytassert_lacks_8bit_bug4s

c�ssddd }|jd�d}�||�r4tS|jd�d}�||�sotd�|f��ntS(s>
            check for bsd wraparound bug (fixed in 2b)
            this is treated as a warning, because it's rare in the field,
            and pybcrypt (as of 2015-7-21) is unpatched, but some people may be stuck with it.

            test cases from <http://www.openwall.com/lists/oss-security/2012/01/02/4>

            NOTE: reference hash is of password "0"*72

            NOTE: if in future we need to deliberately create hashes which have this bug,
                  can use something like 'hashpw(repeat_string(secret[:((1+secret) % 256) or 1]), 72)'
            t
0123456789ii�R=s804$R1lJ2gkNaoPGdafE.H.16.nVyh2niHsGJhayOHLMiXlI45o8/DU.6s804$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Ois.%s backend failed to verify %s wraparound hash(R[RR\R(R!RUR]R^(RWRY(s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytdetect_wrap_bugOsc�s*�|�sdStd�|f��dS(Ns1%s backend unexpectedly has wraparound bug for %s(R\(R!(RWRa(s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pytassert_lacks_wrap_bugjss;$2$04$5BJqKfqMQvV7nS.yUguNcuRfMMOXK0xPWavM7pOzjEi5ze5T1k8/Sttests %s incorrectly rejected $2$ hashs1%r backend lacks $2$ support, enabling workarounds!%s incorrectly rejected $2a$ hashs %s lacks support for $2a$ hashess�passlib.hash.bcrypt: Your installation of the %r backend is vulnerable to the bsd wraparound bug, and should be upgraded or replaced with another backend (enabling workaround for now).R$R%s!%s incorrectly rejected $2y$ hashs2%r backend lacks $2y$ support, enabling workaroundR&s!%s incorrectly rejected $2b$ hashs2%r backend lacks $2b$ support, enabling workaround(t_workrounds_initializedRRYR,t	_bcryptortenginet	SaltErrorR\RQt_lacks_20_supportRSRTtTEST_HASH_2ARBRR/R0Rt_has_2a_wraparound_bugtreplacet_lacks_2y_supporttIDENT_2Yt_lacks_2b_supporttIDENT_2Bt_fallback_ident(
t	mixin_clsRWtdryrunRZR_Rbttest_hash_20tresultttest_hash_2yttest_hash_2b((RWRaRXRYs;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt_finalize_backend_mixinsb
				

	

			

	cC�s|j||jd|j�S(s�
        common helper for backends to implement _calc_checksum().
        takes in secret, returns (secret, ident) pair,
        tnew(t_norm_digest_argsR!tuse_defaults(R9RU((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt_prepare_digest_args�scC�sUt|t�r!|jd�}ntj|�|rD|j|�nt|kretjj|��n|j	r�t
|�dkr�|d }n|tkr�n�|tkr�|j
rK|j}qKn�|tkr�|jrK|j}qKng|tkr |jrK|rt|d�}n|j}qKn+|tkr;td��ntd|��||fS(Nsutf-8i�iHs.$2x$ hashes not currently supported by passlibsunexpected ident value: %r(R>RR[R/tvalidate_secrett_check_truncate_policyt_BNULLR0tNullPasswordErrorRjtlenRBRoRnRpRmRltIDENT_2RhR	R+R\RR(R2RUR!Rx((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRy�s4

			(ssaltsroundssidentR"(.t__name__t
__module__t__doc__tnametsetting_kwdst
checksum_sizeRtcharmaptchecksum_charsRot
default_identR�RBR+Rmtident_valuesRt
ident_aliasest
min_salt_sizet
max_salt_sizet
salt_charstdefault_roundst
min_roundst
max_roundstrounds_costt
truncate_sizeRRdRjRhRlRnRptclassmethodR8R:R<RERHRIRKROt_no_backend_suggestionRwR{Ry(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRYsF		*
				�	t
_NoBackendcB�seZdZd�ZRS(s�
    mixin used before any backend has been loaded.
    contains stubs that force loading of one of the available backends.
    cC�s |j�tt|�j|�S(N(t_stub_requires_backendRDRt_calc_checksum(R9RU((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�s
(R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�	st_BcryptBackendcB�s&eZdZed��Zd�ZRS(s-
    backend which uses 'bcrypt' package
    cC�s�t�r
tSyddlaWntk
r1tSXytjj}Wn tjddt	�d}nXtj
d|�|j||�S(Nis&(trapped) error reading bcrypt versionRPs	<unknown>s%detected 'bcrypt' backend, version %r(RRRt_bcryptRt	__about__RRStwarningRRTRw(RqR�Rrtversion((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt_load_backend_mixin#s	

cC�sh|j|�\}}|j|�}t|t�rE|jd�}ntj||�}|djd�S(NR=i��(R{R<R>RR[R�thashpwR@(R9RUR!R;R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�Is(R�R�R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�s&t_BcryptorBackendcB�s&eZdZed��Zd�ZRS(s/
    backend which uses 'bcryptor' package
    cC�s5yddlaWntk
r$tSX|j||�S(Ni(tbcryptorReRRRw(RqR�Rr((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�`s

cC�sP|j|�\}}|j|�}tjjt�j||�}t|d�S(Ni��(R{R<ReRftEngineRthash_keyR(R9RUR!R;R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�js(R�R�R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�[s
t_PyBcryptBackendcB�s;eZdZdZed��Zd�Zd�ZeZ	RS(s/
    backend which uses 'pybcrypt' package
    cC�s�t�s
tSyddlaWntk
r1tSXytjj}Wn tjddt	�d}nXtj
d|�t|�p�d}|d	kr�td|t
jj�|jdkr�ddl}|j�|_n|jj|_n|j||�S(
Nis((trapped) error reading pybcrypt versionRPs	<unknown>s'detected 'pybcrypt' backend, version %risapy-bcrypt %s has a major security vulnerability, you should upgrade to py-bcrypt 0.3 immediately.(ii(ii(RRRt	_pybcryptRR�RRSR�RRTRRR/R0Rt
_calc_lockRt	threadingtLockt_calc_checksum_threadsafet__func__R�Rw(RqR�RrR�tvinfoR�((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s*	

cC�s!|j�|j|�SWdQXdS(N(R�t_calc_checksum_raw(R9RU((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s
cC�sD|j|�\}}|j|�}tj||�}t|d�S(Ni��(R{R<R�R�R(R9RUR!R;R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��sN(
R�R�R�RR�R�R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�xs!		t_OsCryptBackendcB�s&eZdZed��Zd�ZRS(s0
    backend which uses :func:`crypt.crypt`
    cC�s#tdt�stS|j||�S(NRc(RRiRRw(RqR�Rr((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��scC�sW|j|�\}}|j|�}t||�}|rA|dStjjd��dS(Ni��ssnon-utf8 encoded passwords can't be handled by crypt.crypt() under python3, recommend running `pip install bcrypt`.(R{R<RR/R0tMissingBackendError(R9RUR!R;R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s
	(R�R�R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��st_BuiltinBackendcB�s&eZdZed��Zd�ZRS(sA
    backend which uses passlib's pure-python implementation
    cC�sYddlm}|tjjd��s9tjd�tSddlm	a
|j||�S(Ni(tas_booltPASSLIB_BUILTIN_BCRYPTs@bcrypt 'builtin' backend not enabled via $PASSLIB_BUILTIN_BCRYPT(t
raw_bcrypt(t
passlib.utilsR�tostenvirontgetRSRTRtpasslib.crypto._blowfishR�t_builtin_bcryptRw(RqR�RrR�((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s
cC�sM|j|�\}}t||dd!|jjd�|j�}|jd�S(Nii����R=(R{R�RR[R R@(R9RUR!R7((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s(R�R�R�R�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s
cB�sJeZdZdZeZied6ed6e	d6e
d6ed6ed6Z
RS(s�
This class implements the BCrypt password hash, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt, and a variable number of rounds.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:

    :type salt: str
    :param salt:
        Optional salt string.
        If not specified, one will be autogenerated (this is recommended).
        If specified, it must be 22 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :type rounds: int
    :param rounds:
        Optional number of rounds to use.
        Defaults to 12, must be between 4 and 31, inclusive.
        This value is logarithmic, the actual number of iterations used will be :samp:`2**{rounds}`
        -- increasing the rounds by +1 will double the amount of time taken.

    :type ident: str
    :param ident:
        Specifies which version of the BCrypt algorithm will be used when creating a new hash.
        Typically this option is not needed, as the default (``"2b"``) is usually the correct choice.
        If specified, it must be one of the following:

        * ``"2"`` - the first revision of BCrypt, which suffers from a minor security flaw and is generally not used anymore.
        * ``"2a"`` - some implementations suffered from rare security flaws, replaced by 2b.
        * ``"2y"`` - format specific to the *crypt_blowfish* BCrypt implementation,
          identical to ``"2b"`` in all but name.
        * ``"2b"`` - latest revision of the official BCrypt algorithm, current default.

    :param bool truncate_error:
        By default, BCrypt will silently truncate passwords larger than 72 bytes.
        Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
        to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.

        .. versionadded:: 1.7

    :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.

        .. versionadded:: 1.6

    .. versionchanged:: 1.6
        This class now supports ``"2y"`` hashes, and recognizes
        (but does not support) the broken ``"2x"`` hashes.
        (see the :ref:`crypt_blowfish bug <crypt-blowfish-bug>`
        for details).

    .. versionchanged:: 1.6
        Added a pure-python backend.

    .. versionchanged:: 1.6.3

        Added support for ``"2b"`` variant.

    .. versionchanged:: 1.7

        Now defaults to ``"2b"`` variant.
    RtpybcryptR�tos_crypttbuiltin(sbcryptR�sbcryptorR�R�N(R�R�R�tbackendsRt_backend_mixin_targetR�RR�R�R�R�R�t_backend_mixin_map(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�sAR(t_wrapped_bcryptcB�s<eZdZed�ejD��ZdZed��Z	RS(s�
    abstracts out some bits bcrypt_sha256 & django_bcrypt_sha256 share.
    - bypass backend-loading wrappers for hash() etc
    - disable truncation support, sha256 wrappers don't need it.
    cc�s!|]}|dkr|VqdS(R"N(struncate_error((t.0telem((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pys	<genexpr>_scC�sdS(N((R2RU((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR}ssN(
R�R�R�ttupleRR�RR�R�R}(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�Yst
bcrypt_sha256cB�s�eZdZdZeefZd�e�ZeZe	d�Z
ejdej
�Zed��Zed��Ze	d�Zd�Zd	�ZRS(
s�This class implements a composition of BCrypt+SHA256, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt, and a variable number of rounds.

    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods accept
    all the same optional keywords as the base :class:`bcrypt` hash.

    .. versionadded:: 1.6.2

    .. versionchanged:: 1.7

        Now defaults to ``"2b"`` variant.
    R�c�s#t�fd�tjj�D��S(Nc3�s%|]}|d�kr|VqdS(iN((R�titem(R�(s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pys	<genexpr>�s(tdictRR�titems(R�((R�s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt<lambda>�ss$bcrypt-sha256$s�
        ^
        [$]bcrypt-sha256
        [$](?P<variant>2[ab])
        ,(?P<rounds>\d{1,2})
        [$](?P<salt>[^$]{22})
        (?:[$](?P<digest>.{31}))?
        $
        cC�s)tj|�}|stS|j|j�S(N(R/tto_unicode_for_identifyRRAtprefix(R2R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyRG�scC�s�t|dd�}|j|j�s9tjj|��n|jj|�}|sftjj|��n|j	d�}|jtj
�r�|tj
kr�tjj|��n|d|j	d�dt|�d|j	d�d|j	d��S(	NR=R3R R!tvariantRR)tdigest(
RRAR�R/R0tInvalidHashErrort_hash_retmatchR1tgroupt_UZEROtZeroPaddedRoundsErrorR.(R2R3tmR ((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR8�s!s$bcrypt-sha256$%s,%d$%s$%scC�s8|j|jjt�|j|j|jf}t|�S(N(t	_templateR!tstript_UDOLLARR RR)R(R9R3((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR:�scC�sOt|t�r!|jd�}ntt|�j��}tt|�j|�S(Nsutf-8(	R>RR[RRR�RDR�R�(R9RUtkey((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR��s(R�R�R�R�RBRoR�R�R�RR�tretcompiletXR�R�RGR8R�R:R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyR�|s
		(GR�t
__future__RRtbase64RthashlibRR�R�tloggingt	getLoggerR�RStwarningsRRR�R�ReR�tpasslib.excRRRR�RR	R
RRR
RRtpasslib.utils.binaryRtpasslib.utils.compatRRRRtpasslib.utils.handlerstutilsthandlersR/t__all__R�RBR+RmRoR~RiRtSubclassBackendMixint
TruncateMixint
HasManyIdentst	HasRoundstHasSalttGenericHandlerRR�R�R�R�R�R�RR�R�R�(((s;/usr/lib/python2.7/site-packages/passlib/handlers/bcrypt.pyt<module>	sN:"		%"��=A#b#