+
    ¢THi�œ  ã            
      óð  € R t ^ RIHt ^ RIt^ RIHt ^ RIHt ^ RIH	t	 ^ RI
Ht ^ RIHt ^ RIHu Ht ^ RIHt ^ R	IHt ^ R
IHtHt ^ RIHtHtHtHt ^ RIHt Rs R.t!Rt"Rt#Rt$Rt%Rt&Rt'Rt(R t) ! R R]PT                  ]PV                  ]PX                  ]PZ                  ]P\                  ]P^                  4      t0 ! R R]04      t1 ! R R]04      t2 ! R R]1]04      t3Rt4 ! R R]34      t5 ! R  R!]54      t6R# )"zÎ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
)ÚannotationsN)Ú	b64encode)Úsha256)Úmetadata)Ú	find_spec)Úwarn)Úlogger)Úcompile_hmac)ÚPasslibHashWarningÚPasslibSecurityError)Úrepeat_stringÚ
to_unicodeÚutf8_repeat_stringÚutf8_truncate)Úbcrypt64Úbcryptz$2$z$2a$z$2x$z$2y$z$2b$ó    z<$2a$04$5BJqKfqMQvV7nS.yUguNcueVirQqDBGaLXSqj.rs.pZPlNR0UX/HKc                 óV   € \        R4      f   R#  ^ RIHp  R#   \         d     R# i ; i)aõ  
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.
r   F©Ú__version__T)r   Úbcrypt._bcryptr   ÚImportErrorr   s    Ú9/usr/lib/python3/dist-packages/passlib/handlers/bcrypt.pyÚ_detect_pybcryptr   1   s5   € ô( �ÓÒ"Ùð
õ	
ñ
 øô ô Úðús   ‘ ™(§(c                  óŽ  a € ] tR t^Tt$ RtRtRtR]R&   ^t]	P                  t]t]]]]]3tR]R&   R]R]R]R	]/t^;tt]	P                  tR
t^t^t^tRt^HtR]R&   RtRtRtRt Rt!]t"Rt#Rt$]%R 4       t&R t'R t(]%V 3R l4       t)]%R 4       t*]%V 3R l4       t+]%V 3R l4       t,RV 3R llt-Rt.]%R 4       t/R t0]%RR l4       t1Rt2V ;t3# )Ú_BcryptCommona  
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.
r   ztuple[str, ...]Úsetting_kwdsÚident_valuesÚ2Ú2aÚ2yÚ2bz.OeuÚlog2ú
int | NoneÚtruncate_sizeFc                	ó<  € V P                  V4      w  r#V\        8X  d   \        R 4      hVP                  R4      w  rE\	        V4      pVRV3,          8w  d!   \
        P                  P                  V R4      hVR,          VR,          r‡T ! TTT;'       g    RVR7      # )z>crypt_blowfish's buggy '2x' hashes are not currently supportedÚ$z%02dzmalformed cost field:Né   N:r'   NNN)ÚroundsÚsaltÚchecksumÚident)Ú_parse_identÚIDENT_2XÚ
ValueErrorÚsplitÚintÚuhÚexcÚMalformedHashError)	ÚclsÚhashr+   ÚtailÚ
rounds_strÚdatar(   r)   Úchks	   &&       r   Úfrom_stringÚ_BcryptCommon.from_string�   sœ   € à×&Ñ& tÓ,‰ˆØ”HÔÜØPóð ð  Ÿ:™: c›?Ñˆ
Ü�Z“ˆØ˜ 6 )Õ+Ô+Ü—&‘&×+Ñ+¨CÐ1GÓHÐHØ˜•I˜t C�yˆcÙØØØ—[�[˜DØô	
ð 	
ó    c                	ól   € R V P                   V P                  V P                  V P                  3,          # )z%s%02d$%s%s)r+   r(   r)   r*   )Úselfs   &r   Ú	to_stringÚ_BcryptCommon.to_string°   s&   € Ø §
¡
¨D¯K©K¸¿¹ÀDÇMÁMÐRÕRÐRr<   c                ó@   € RWP                   V P                  3,          # )z5internal helper to prepare config string for backendsz	%s%02d$%s)r(   r)   )r>   r+   s   &&r   Ú_get_configÚ_BcryptCommon._get_configµ   s   € à˜e§[¡[°$·)±)Ð<Õ<Ð<r<   c                	óÞ   <€ \        V\        4      '       d   VP                  R 4      pVP                  \        4      '       d   V^,          V P
                  9  d   R# \        SV `  ! V3/ VB # )ÚasciiT)Ú
isinstanceÚbytesÚdecodeÚ
startswithÚIDENT_2AÚfinal_salt_charsÚsuperÚneeds_update)r4   r5   ÚkwdsÚ	__class__s   &&,€r   rM   Ú_BcryptCommon.needs_update¹   sZ   ø€ ô
 �dœE×"Ò"Ø—;‘;˜wÓ'ˆDØ�?‰?œ8×$Ò$¨¨b­¸×9MÑ9MÔ)MÙô
 ‰wÒ# DÑ1¨DÑ1Ð1r<   c                ór   € V P                  V4      '       d    V P                  V4      P                  4       # V# )z<helper to normalize hash, correcting any bcrypt padding bits)Úidentifyr:   r?   ©r4   r5   s   &&r   ÚnormhashÚ_BcryptCommon.normhashÈ   s0   € ð �<‰<˜×ÒØ—?‘? 4Ó(×2Ñ2Ó4Ð4Øˆr<   c                	óL   <€ \         SV `  4       p\        P                  ! V4      # ©N)rL   Ú_generate_saltr   Úrepair_unused)r4   r)   rO   s   & €r   rX   Ú_BcryptCommon._generate_saltÏ   s#   ø€ ô ‰wÑ%Ó'ˆÜ×%Ò% dÓ+Ð+r<   c                	ó    <€ \         SV `  ! V3/ VB pVf   Q R4       h\        P                  ! V4      w  r1V'       d   \	        R\
        4       V# )Nz!HasSalt didn't generate new salt!z—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)rL   Ú
_norm_saltr   Úcheck_repair_unusedr   r
   )r4   r)   rN   ÚchangedrO   s   &&, €r   r\   Ú_BcryptCommon._norm_saltÖ   sZ   ø€ ä‰wÒ! $Ñ/¨$Ñ/ˆØÒÐDÐ!DÓDÐÜ ×4Ò4°TÓ:‰ˆßô ðGô #ô	ð ˆr<   c                	óˆ   <€ \         SV `  WR 7      p\        P                  ! V4      w  r1V'       d   \	        R\
        4       V# ))Úrelaxedz—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)rL   Ú_norm_checksumr   r]   r   r
   )r>   r*   ra   r^   rO   s   &&& €r   rb   Ú_BcryptCommon._norm_checksumæ   sE   ø€ Ü‘7Ñ)¨(Ð)ÓDˆÜ$×8Ò8¸ÓBÑˆßÜðGô #ô	ð ˆr<   z9 -- recommend you install one (e.g. 'pip install bcrypt')c                óð  a aa
aa€ S \         P                  S,          J g   Q R4       hS P                  '       d   R# S P                  o\        \
        P                  P                  3oVVV3R lpVV3R lpVV V3R lo
VV
3R lpRpV! RV4      pV\        J d    RS n	        \        P                  ! R	S4       MV'       g   \        S R
24      hV! R\        4      pV\        J d   \        S R24      hV'       g   \        S R24      hV! \        4       S
! \        4      '       dP   SR8X  d   \        P                  ! RS4       M)\        RS: R2\
        P                  P                   4       RS n        \        P%                  RR4      pV! RV4      pV\        J d    RS n        \        P                  ! RS4       M.V'       g   \        S R24      hV! \(        4       V! \(        4       \        P%                  RR4      p	V! RV	4      pV\        J d    RS n        \        P                  ! RS4       M9V'       g   \        S R24      h\,        S n        V! \,        4       V! \,        4       RS n        R# )z¸
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.
z1_configure_workarounds() invoked from wrong classTc           	     ó¾   <€  S! W4      #   S d
    \         u # \        P                  P                   d%    \        P
                  ! RST TRR7       \         u # i ; i)z8verify() wrapper which traps 'unknown identifier' errorsz<trapped unexpected response from %r backend: verify(%r, %r):T©Úexc_info)ÚNotImplementedr1   r2   ÚInternalBackendErrorr   Údebug)Úsecretr5   ÚbackendÚ	err_typesÚverifys   &&€€€r   Úsafe_verifyÚ:_BcryptCommon._finalize_backend_mixin.<locals>.safe_verify  sa   ø€ ð&Ù˜fÓ+Ð+øØô &ô &Ò%Ü—6‘6×.Ñ.ô &ô —’ØRØØØØ!õô &Ò%ð&ús   ƒ ‹AšA·"AÁAc                óî   <€ RpV P                  R4      R,           pV P                  R4      R,           pS! W4      '       d   \        RS: RV : R24      hS! W4      '       g   \        S RV  R	24      hR
# )aÊ  
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   Ñ‘rE   s8   05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcASs8   05$6bNw2HLQYeqHYyBfLMsv/OUcZd0LKP39b87nBw3.S2tVZSqiQX6euú.passlib.hash.bcrypt: Your installation of the zM backend is vulnerable to the crypt_blowfish 8-bit bug (CVE-2011-2483) under z@ hashes, and should be upgraded or replaced with another backendú backend failed to verify z
 8bit hashN)Úencoder   ÚRuntimeError)r+   rk   Úbug_hashÚcorrect_hashrl   rn   s   &   €€r   Úassert_lacks_8bit_bugÚD_BcryptCommon._finalize_backend_mixin.<locals>.assert_lacks_8bit_bug2  s¬   ø€ ð0 !ˆFà—‘˜WÓ%ØMõNð ð
 —‘˜WÓ%ØMõNð ñ
 �f×'Ò'ô +ØDÀWÁKð PJØJOÉð SNðNóð ñ ˜&×/Ò/Ü"Ø�iÐ9¸%¸À
ÐKóð ñ 0r<   c                ó  <€ R	pSP                   '       g*   V P                  R4      R,           pS! W4      '       d   R# MVRSP                   pV P                  R4      R,           pS! W4      '       g   \        S RV  R24      hR# )
aÞ  
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)'
rE   s8   04$R1lJ2gkNaoPGdafE.H.16.nVyh2niHsGJhayOHLMiXlI45o8/DU.6TNs8   04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oirs   z wraparound hashFsÿ   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234)Ú_backend_raises_on_truncatert   r$   ru   )r+   rk   rv   rw   rl   Ú	mixin_clsrn   s   &   €€€r   Údetect_wrap_bugÚ>_BcryptCommon._finalize_backend_mixin.<locals>.detect_wrap_buge  s©   ø€ ð 0ˆFà×8×8Ð8ð —L‘L Ó)ØQõRð ñ
 ˜&×+Ò+Ùð ,ð  Ð 8 ×!8Ñ!8Ð9�ð
 —‘˜WÓ%ØMõNð ñ ˜&×/Ò/Ü"Ø�iÐ9¸%¸Ð@PÐQóð ñ r<   c                óD   <€ S! V 4      '       g   R # \        S RV  24      h)Nz- backend unexpectedly has wraparound bug for )ru   )r+   rl   r}   s   &€€r   Úassert_lacks_wrap_bugÚD_BcryptCommon._finalize_backend_mixin.<locals>.assert_lacks_wrap_bug’  s/   ø€ Ù" 5×)Ò)Ùô Ø�)ÐHÈÈÐPóð r<   s;   $2$04$5BJqKfqMQvV7nS.yUguNcuRfMMOXK0xPWavM7pOzjEi5ze5T1k8/SÚtestz1%r backend lacks $2$ support, enabling workaroundz incorrectly rejected $2$ hashz lacks support for $2a$ hashesz incorrectly rejected $2a$ hashÚos_cryptz;%r backend has $2a$ bsd wraparound bug, enabling workaroundrr   zˆ backend is vulnerable to the bsd wraparound bug, and should be upgraded or replaced with another backend (enabling workaround for now).r   r    z2%r backend lacks $2y$ support, enabling workaroundz incorrectly rejected $2y$ hashr!   z2%r backend lacks $2b$ support, enabling workaroundz incorrectly rejected $2b$ hash)r   Ú_backend_mixin_mapÚ_workrounds_initializedrn   r.   r1   r2   ÚMissingBackendErrorrh   Ú_lacks_20_supportr   rj   ru   ÚTEST_HASH_2ArJ   r   ÚPasslibSecurityWarningÚ_has_2a_wraparound_bugÚreplaceÚ_lacks_2y_supportÚIDENT_2YÚ_lacks_2b_supportÚIDENT_2BÚ_fallback_ident)r|   rl   Údryrunro   rx   r€   Útest_hash_20ÚresultÚtest_hash_2yÚtest_hash_2br}   rm   rn   s   ff&       @@@r   Ú_finalize_backend_mixinÚ%_BcryptCommon._finalize_backend_mixin  s;  ü€ ð œF×5Ñ5°gÕ>Ó>ð 	
Ø?ó	
Ð>ð ×,×,Ð,Ùà×!Ñ!ˆä¤§¡×!;Ñ!;Ð<ˆ	÷	&ö41	÷f+	öZ	ð VˆÙ˜V \Ó2ˆØ”^Ó#Ø*.ˆIÔ'Ü�LŠLÐLÈgÕVßÜ ' Ð*HÐIÓJÐJñ
 ˜V¤\Ó2ˆØ”^Ó#ä ' Ð*HÐIÓJÐJßÜ ' Ð*IÐJÓKÐKÙœhÔ'Ùœ8×$Ò$Ø˜*Ô$ô —’ØQØõô ØDÀWÁKð P5ð 5ô —F‘F×1Ñ1ôð 04ˆIÔ,ô
 $×+Ñ+¨D°$Ó7ˆÙ˜V \Ó2ˆØ”^Ó#Ø*.ˆIÔ'Ü�LŠLÐMÈwÕWßÜ ' Ð*IÐJÓKÐKñ "¤(Ô+Ù!¤(Ô+ô $×+Ñ+¨D°$Ó7ˆÙ˜V \Ó2ˆØ”^Ó#Ø*.ˆIÔ'Ü�LŠLÐMÈwÕWßÜ ' Ð*IÐJÓKÐKä(0ˆIÔ%Ù!¤(Ô+Ù!¤(Ô+ð -1ˆ	Ô)Ùr<   c                óP   € V P                  WP                  V P                  R7      # )zj
common helper for backends to implement _calc_checksum().
takes in secret, returns (secret, ident) pair,
)Únew)Ú_norm_digest_argsr+   Úuse_defaults©r>   rk   s   &&r   Ú_prepare_digest_argsÚ"_BcryptCommon._prepare_digest_argsï  s$   € ð
 ×%Ñ% f¯j©j¸d×>OÑ>OÐ%ÓPÐPr<   c                	óº  € V P                   p\        V\        4      '       d   VP                  R 4      pMV'       d    VP	                  R 4       \        P                  ! V4       V'       d   V P                  V4       \        V9   d    \        P                  P                  V 4      hV P                  '       d/   \        V4      ^ÿ8¼  d   V'       d   \        V^H4      pM	VR,          pV\        8X  d    W3# V\         8X  d"   V P"                  '       d   V P$                  pW3# V\&        8X  d"   V P(                  '       d   V P$                  pW3# V\*        8X  dK   V P,                  '       d6   V'       d"   V'       d   \/        V^H4      pM\1        V^H4      pV P$                  pW3# V\2        8X  d   \5        R4      h\7        RV: 24      h  \
         d    Rp ELŠi ; i)úutf-8FºNéH   Nz.$2x$ hashes not currently supported by passlibzunexpected ident value: )Ú_require_valid_utf8_bytesrF   Ústrrt   rH   ÚUnicodeDecodeErrorr1   Úvalidate_secretÚ_check_truncate_policyÚ_BNULLr2   ÚNullPasswordErrorrŠ   Úlenr   rJ   r�   rŽ   r�   r�   rŒ   ÚIDENT_2r‡   r   r   r-   ru   ÚAssertionError)r4   rk   r+   r™   Úrequire_valid_utf8_bytess   &&&& r   rš   Ú_BcryptCommon._norm_digest_argsö  s»  € ð $'×#@Ñ#@Ð Ü�fœc×"Ò"Ø—]‘] 7Ó+‰Fß%ð1Ø—‘˜gÔ&ô 	×Ò˜6Ô"÷ Ø×&Ñ& vÔ.ô
 �VÔÜ—&‘&×*Ñ*¨3Ó/Ð/ð ×%×%Ð%¬#¨f«+¸Ô*<ß'ô ' v¨rÓ2‘à ��ð ”HÔàðN ˆ}ÐðK ”hÔØ×$×$Ð$ð
 ×+Ñ+�ð> ˆ}Ðð; ”hÔØ×$×$Ð$ð ×+Ñ+�ð2 ˆ}Ðð/ ”gÔØ×$×$Ð$÷ ß/ô "4°F¸BÓ!?™ä!.¨v°rÓ!:˜Ø×+Ñ+�ð ˆ}Ðð ”hÔô ÐOÓPÐPô !Ð#;¸E¹9Ð!EÓFÐFøôU &ô 1ð ,1Ó(ð1ús   ¾G	 Ç	GÇG© )r)   r(   r+   Útruncate_error©F)4Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Únamer   Ú__annotations__Úchecksum_sizer   ÚcharmapÚchecksum_charsr�   Údefault_identr«   rJ   r-   r�   r   Úident_aliasesÚmin_salt_sizeÚmax_salt_sizeÚ
salt_charsrK   Údefault_roundsÚ
min_roundsÚ
max_roundsÚrounds_costr$   r…   rŠ   r‡   rŒ   rŽ   r�   r£   r{   Úclassmethodr:   r?   rB   rM   rT   rX   r\   rb   Ú_no_backend_suggestionr–   r�   rš   Ú__static_attributes__Ú__classcell__©rO   s   @r   r   r   T   s{  ø‡ ñð €DØ$Q€L�/ÓQð
 €MØ×%Ñ%€Nð
 €MØ%,¨h¸À(ÈHÐ$U€L�/ÓUØ˜' 4¨°4¸À4ÈÐR€Mð
 %'Ð&€M�MØ×!Ñ!€Jð Ðð
 €NØ€JØ€JØ€Kð
 !#€M�:Ó"ð $ÐØ"ÐØÐØÐØÐØ€OØ %ÐØ"'Ðàñ
ó ð
ò$Sò
=ð ô2ó ð2ð ñó ðð ô,ó ð,ð ôó ð÷
ð6 YÐàñgó ðgòVQð óVó öVr<   r   c                  ó    € ] tR tRtRtR tRtR# )Ú
_NoBackendiP  zt
mixin used before any backend has been loaded.
contains stubs that force loading of one of the available backends.
c                	óD   € V P                  4        V P                  V4      # rW   )Ú_stub_requires_backendÚ_calc_checksumrœ   s   &&r   rÎ   Ú_NoBackend._calc_checksumV  s!   € Ø×#Ñ#Ô%ð ×"Ñ" 6Ó*Ð*r<   r¯   N)r²   r³   r´   rµ   r¶   rÎ   rÇ   r¯   r<   r   rË   rË   P  s   † ñö
+r<   rË   c                  ó0   € ] tR tRtRt]R 4       tR tRtR# )Ú_BcryptBackendi]  z%
backend which uses 'bcrypt' package
c                	ó‚  € \        4       '       d   R #  ^ RIs \        P
                  ! R4      p\        TP                  R4      ^ ,          4      ^8¼  d   RT n        \        P                  ! RT4       T P                  Y4      #   \         d     R # i ; i  \         d    \        P                  ! RRR7       Rp Lai ; i)	FNr   Ú.Tz&(trapped) error reading bcrypt versionrf   z	<unknown>z%detected 'bcrypt' backend, version %r)r   r   Ú_bcryptr   r   Úversionr0   r/   r{   Ú	Exceptionr   Úwarningrj   r–   )r|   r·   r‘   rÕ   s   &&& r   Ú_load_backend_mixinÚ"_BcryptBackend._load_backend_mixinb  sª   € ô ×Òáð	Û$ð	"Ü×&Ò& xÓ0ˆGä�7—=‘= Ó% aÕ(Ó)¨QÔ.Ø8<�	Ô5ô
 	�ŠÐ<¸gÔFà×0Ñ0°Ó>Ð>øô ô 	Úð	ûô ô 	"Ü�NŠNÐCÈdÕSØ!ŠGð	"ús#   ”B ™AB ÂBÂBÂ%B>Â=B>c                	ó  € V P                  V4      w  rV P                  V4      p\        V\        4      '       d   VP	                  R 4      pV P
                  '       d
   VR,          p\        P                  W4      p\        V\        4      '       g   Q hVP                  V4      '       d!   \        V4      \        V4      ^,           8w  d#   \        P                  P                  WVRR7      hVRR P                  R 4      # )rE   r¡   z`bcrypt` package)ÚsourceNiáÿÿÿ)r�   rB   rF   r¤   rt   r{   rÔ   ÚhashpwrG   rI   rª   r1   r2   ÚCryptBackendErrorrH   )r>   rk   r+   Úconfigr5   s   &&   r   rÎ   Ú_BcryptBackend._calc_checksumŒ  s×   € ð
 ×1Ñ1°&Ó9‰ˆØ×!Ñ! %Ó(ˆÜ�fœc×"Ò"Ø—]‘] 7Ó+ˆFà×+×+Ð+Ø˜C•[ˆFä�~‰~˜fÓ-ˆÜ˜$¤×&Ò&Ð&Ð&Ø�‰˜v×&Ò&¬#¨d«)´s¸6³{ÀRÕ7GÔ*GÜ—&‘&×*Ñ*Ø˜dÐ+=ð +ó ð ð �C�Dˆz× Ñ  Ó)Ð)r<   r¯   N)	r²   r³   r´   rµ   r¶   rÅ   rØ   rÎ   rÇ   r¯   r<   r   rÑ   rÑ   ]  s!   † ñð ñ?ó ð?öR*r<   rÑ   c                  ó.   € ] tR tRtRtRtRtR]R ]/t	Rt
R# )r   i¢  a
  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.
TNr¯   )r   )r²   r³   r´   rµ   r¶   ÚbackendsÚ_backend_mixin_targetrË   rÑ   r„   rÇ   r¯   r<   r   r   r   ¢  s,   † ñ@ðP €Hð !Ðð 	ˆjØ�.ðÔr<   r&   c                  ó²   € ] tR tRt$ Rt];QJ d    . R ]P                   4       F  NK  	  5M! R ]P                   4       4      tRtR]	R&   ]
R 4       tRtR# )	Ú_wrapped_bcryptiü  z³
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.
c              #  	ó6   "  € T F  qR9  g   K  Vx € K  	  R# 5i)r°   N)r°   r¯   )Ú.0Úelems   & r   Ú	<genexpr>Ú_wrapped_bcrypt.<genexpr>  s   é € ð Ù,�Ð<NÑ0N�ŠÓ,ùs   ‚�
Nr#   r$   c                	ó   € R # rW   r¯   )r4   rk   s   &&r   r§   Ú&_wrapped_bcrypt._check_truncate_policy  s   € ñ 	r<   r¯   )r²   r³   r´   rµ   r¶   Útupler   r   r$   r¸   rÅ   r§   rÇ   r¯   r<   r   rä   rä   ü  s_   ‡ ñ÷ �5ñ Ø×,Ò,ó—5‘5ñ Ø×,Ò,óó €Lð !%€M�:Ó$ð& ñó ôr<   rä   c                  ó  a € ] tR tRtRtR t]]3tR ! ]4      t	]t
^^0t^t]RV 3R ll4       tRt]P"                  ! R4      t]P"                  ! R4      t]R 4       t]R	 4       tR
tRtR tRV 3R llt]R 4       tV 3R ltV 3R ltRtV ;t# )Úbcrypt_sha256i  aÃ  
This class implements a composition of BCrypt + HMAC_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"`` bcrypt variant; though supports older hashes
    generated using the ``"2a"`` bcrypt variant.

.. versionchanged:: 1.7.3

    For increased security, updated to use HMAC-SHA256 instead of plain SHA256.
    Now only supports the ``"2b"`` bcrypt variant.  Hash format updated to "v=2".
c                	óf   a € \        V 3R  l\        P                  P                  4        4       4      # )c              3  óF   <"  € T F  q^,          S9   g   K  Vx € K  	  R# 5i)é   Nr¯   )ræ   Úitemr   s   & €r   rè   Ú)bcrypt_sha256.<lambda>.<locals>.<genexpr>C  s    øé € ð "
Ù9�TÀ!½WÈÑ=T�DŠDÓ9ùs   ƒ!—
!)Údictr   r½   Úitems)r   s   fr   Ú<lambda>Úbcrypt_sha256.<lambda>C  s&   ø€ œTô "
Ü#×1Ñ1×7Ñ7Ô9ó"
ô 
r<   c                	óæ   <€ \         SV `  ! R/ VB pVe   VP                  V4      Vn        VP                  pVP                  ^8”  d)   V\
        8w  d   \        RV: RVP                  : 24      hV# )Nzbcrypt z  hashes not allowed for version r¯   )rL   ÚusingÚ_norm_versionrÕ   r¼   r�   r.   )r4   rÕ   rN   Úsubclsr+   rO   s   &&,  €r   rù   Úbcrypt_sha256.usingT  st   ø€ ä‘’Ñ& Ñ&ˆØÒØ#×1Ñ1°'Ó:ˆFŒNØ×$Ñ$ˆØ�>‰>˜AÔ %¬8Ô"3ÜØ˜%™Ð"BÀ6Ç>Á>ÑBTÐUóð ð ˆr<   z$bcrypt-sha256$zÒ(?x)
        ^
        [$]bcrypt-sha256[$]
        v=(?P<version>\d+),
        t=(?P<type>2b),
        r=(?P<rounds>\d{1,2})
        [$](?P<salt>[^$]{22})
        (?:[$](?P<digest>[^$]{31}))?
        $
        zµ(?x)
        ^
        [$]bcrypt-sha256[$]
        (?P<type>2[ab]),
        (?P<rounds>\d{1,2})
        [$](?P<salt>[^$]{22})
        (?:[$](?P<digest>[^$]{31}))?
        $
        c                	óx   € \         P                  ! V4      pV'       g   R # VP                  V P                  4      # r±   )r1   Úto_unicode_for_identifyrI   ÚprefixrS   s   &&r   rR   Úbcrypt_sha256.identify†  s+   € ä×)Ò)¨$Ó/ˆßÙØ�‰˜sŸz™zÓ*Ð*r<   c           	     	óH  € \        VR R4      pVP                  V P                  4      '       g    \        P                  P                  V 4      hV P                  P                  V4      pV'       dB   \        VP                  R4      4      pV^8  d    \        P                  P                  V 4      hMEV P                  P                  V4      pV'       d   ^pM\        P                  P                  V 4      hVP                  R4      pVP                  \        P                  4      '       d5   V\        P                  8w  d    \        P                  P                  V 4      hV ! VVP                  R4      \        V4      VP                  R4      VP                  R4      R7      # )rE   r5   rÕ   r(   Útyper)   Údigest)rÕ   r+   r(   r)   r*   )r   rI   rÿ   r1   r2   ÚInvalidHashErrorÚ_v2_hash_reÚmatchr0   Úgroupr3   Ú_v1_hash_reÚ_UZEROÚZeroPaddedRoundsError)r4   r5   ÚmrÕ   r(   s   &&   r   r:   Úbcrypt_sha256.from_string�  s2  € ä˜$ ¨Ó0ˆØ�‰˜sŸz™z×*Ò*Ü—&‘&×)Ñ)¨#Ó.Ð.Ø�O‰O×!Ñ! $Ó'ˆßÜ˜!Ÿ'™' )Ó,Ó-ˆGØ˜Œ{Ü—f‘f×/Ñ/°Ó4Ð4ð ð —‘×%Ñ% dÓ+ˆAßØ‘ä—f‘f×/Ñ/°Ó4Ð4Ø—‘˜Ó"ˆØ×ÑœRŸY™Y×'Ò'¨F´b·i±iÔ,?Ü—&‘&×.Ñ.¨sÓ3Ð3ÙØØ—'‘'˜&“/Ü�v“;Ø—‘˜“Ø—W‘W˜XÓ&ô
ð 	
r<   z"$bcrypt-sha256$v=2,t=%s,r=%d$%s$%sz$bcrypt-sha256$%s,%d$%s$%sc                	óæ   € V P                   ^8X  d   V P                  pMV P                  pVV P                  P	                  \
        4      V P                  V P                  V P                  3,          # )rñ   )	rÕ   Ú_v1_templateÚ_v2_templater+   ÚstripÚ_UDOLLARr(   r)   r*   )r>   Útemplates   & r   r?   Úbcrypt_sha256.to_string«  s]   € Ø�<‰<˜1ÔØ×(Ñ(‰Hà×(Ñ(ˆHØØ�J‰J×ÑœXÓ&Ø�K‰KØ�I‰IØ�M‰Mð	
õ 
ð 	
r<   c                	ó\   <€ Ve   V P                  V4      V n        \        SV `  ! R/ VB  R # )Nr¯   )rú   rÕ   rL   Ú__init__)r>   rÕ   rN   rO   s   &&,€r   r  Úbcrypt_sha256.__init__·  s+   ø€ ØÒØ×-Ñ-¨gÓ6ˆDŒLÜ‰ÒÑ ˜4Ô r<   c                	ó\   € WP                   9  d   \        V P                   R V: 24      hV# )z": unknown or unsupported version: )Ú_supported_versionsr.   r·   )r4   rÕ   s   &&r   rú   Úbcrypt_sha256._norm_version¼  s.   € à×1Ñ1Ô1Ü §¡˜zÐ)KÈGÉ;ÐWÓXÐXØˆr<   c                	ó|  <€ \        V\        4      '       d   VP                  R 4      pV P                  ^8X  d   \	        V4      P                  4       pMPV P                  pVR,          V P                  9  d   \        R4      h\        RVP                  R4      4      ! V4      p\        V4      p\        SV `1  V4      # )r    zinvalid salt stringr   rE   éÿÿÿÿ)rF   r¤   rt   rÕ   r   r  r)   rK   r.   r	   r   rL   rÎ   )r>   rk   r  r)   ÚkeyrO   s   &&   €r   rÎ   Úbcrypt_sha256._calc_checksumÂ  s£   ø€ ô �fœc×"Ò"Ø—]‘] 7Ó+ˆFà�<‰<˜1Ôô ˜F“^×*Ñ*Ó,‰Fð —9‘9ˆDØ�B�x˜t×4Ñ4Ô4ô !Ð!6Ó7Ð7Ü! (¨D¯K©K¸Ó,@ÔAÀ&ÓIˆFô ˜Óˆô ‰wÑ% cÓ*Ð*r<   c                	óp   <€ V P                   \        V 4      P                   8  d   R # \        SV `  ! R/ VB # )Tr¯   )rÕ   r  rL   Ú_calc_needs_update)r>   rN   rO   s   &,€r   r  Ú bcrypt_sha256._calc_needs_updateé  s/   ø€ Ø�<‰<œ$˜t›*×,Ñ,Ô,ÙÜ‰wÒ)Ñ1¨DÑ1Ð1r<   )rÕ   rW   )r²   r³   r´   rµ   r¶   r·   rJ   r�   r   r½   r¼   r  rÕ   rÅ   rù   rÿ   ÚreÚcompiler  r  rR   r:   r  r  r?   r  rú   rÎ   r  rÇ   rÈ   rÉ   s   @r   rî   rî     së   ø† ñð2 €Dð ˜hÐ'€Lò	
ð ó	€Mð
 €Mð ˜a˜&Ðð
 €Gàö	ó ð	ð0 €Fð —*’*ð 	ó 	€Kð —*’*ð ó €Kð ñ+ó ð+ð ñ
ó ð
ð4 8€LØ/€Lò

÷!ð
 ñó ðõ
%+÷N2ó 2r<   rî   )7r¶   Ú
__future__r   r!  Úbase64r   Úhashlibr   Ú	importlibr   Úimportlib.utilr   Úwarningsr   Úpasslib.utils.handlersÚutilsÚhandlersr1   Úpasslib._loggingr   Úpasslib.crypto.digestr	   Úpasslib.excr
   r   Úpasslib.utilsr   r   r   r   Úpasslib.utils.binaryr   rÔ   Ú__all__r«   rJ   r-   r�   r�   r¨   rˆ   r   ÚSubclassBackendMixinÚTruncateMixinÚHasManyIdentsÚ	HasRoundsÚHasSaltÚGenericHandlerr   rË   rÑ   r   r  rä   rî   r¯   r<   r   Ú<module>r8     s  ðñõ #ã 	Ý Ý Ý Ý $Ý ç #Ð #Ý #Ý .ß @÷ó õ *à
€ð ð€ð €Ø€Ø€Ø€Ø€Ø	€ð N€ò ôFyØ×ÑØ×ÑØ×ÑØ‡L�LØ‡J�JØ×Ñôyôx
+�ô 
+ôB*�]ô B*ôJRˆZ˜ô Rðj €ô
 �fô  ôFM2�Oö M2r<   