
     hN              
          d Z ddlmZmZ ddlmZ ddlmZ ddlZddl	Z	ddl
Z
 e
j                  e      ZddlmZ dadadadaddlmZ ddlmZmZmZ dd	lmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% dd
l&m'Z' ddl(m)Z) ddl(m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ ddl0m1c m2Z3 dgZ4 e*d      Z5 e*d      Z6 e*d      Z7 e*d      Z8 e*d      Z9dZ:dZ;d Z< G d de3jz                  e3j|                  e3j~                  e3j                  e3j                  e3j                        ZC G d deC      ZD G d deC      ZE G d deC      ZF G d deC      ZG G d  d!eC      ZH G d" d#eC      ZI G d$ deDeC      ZJ e*d%      ZK G d& d'eJ      ZL G d( d)eL      ZMy)*zpasslib.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
    )with_statementabsolute_import)	b64encode)sha256N)warn)compile_hmac)PasslibHashWarningPasslibSecurityWarningPasslibSecurityError)
safe_cryptrepeat_stringto_bytesparse_versionrng
getrandstr
test_crypt
to_unicodeutf8_truncateutf8_repeat_stringcrypt_accepts_bytes)bcrypt64)get_unbound_method_function)uuascii_to_strunicodestr_to_uasciiPY3
error_frombcryptz$2$z$2a$z$2x$z$2y$z$2b$    z<$2a$04$5BJqKfqMQvV7nS.yUguNcueVirQqDBGaLXSqj.rs.pZPlNR0UX/HKc                  X    	 ddl } 	 ddlm} y# t        $ r Y yw xY w# t        $ r Y yw xY w)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   N)__version__FT)r   ImportErrorbcrypt._bcryptr"   )r   r"   s     Y/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/passlib/handlers/bcrypt.py_detect_pybcryptr&   7   s@    (.      s     		))c            	           e Zd ZdZdZdZdZej                  Z	e
Zeeeee
fZ ed      e ed      e ed      e ed      e
iZd	xZZej                  Zd
ZdZdZdZdZdZdZdZdZdZdZ eZ!dZ"e#d        Z$d Z%d Z&e# fd       Z'e#d        Z(e# fd       Z)e# fd       Z*d fd	Z+dZ,e#d        Z-d Z.e#dd       Z/ xZ0S )_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   )saltroundsidenttruncate_error   22a2y2b   z.Oeu      log2H   Fc                 :   | j                  |      \  }}|t        k(  rt        d      |j                  t	        d            \  }}t        |      }|t	        d      |fz  k7  r t        j                  j                  | d      |d d |dd  }} | |||xs d |      S )Nz>crypt_blowfish's buggy '2x' hashes are not currently supported$z%02dzmalformed cost fieldr2   )r*   r)   checksumr+   )	_parse_identIDENT_2X
ValueErrorsplitr   intuhexcMalformedHashError)	clshashr+   tail
rounds_strdatar*   r)   chks	            r%   from_stringz_BcryptCommon.from_string   s    &&t,tH 3 4 4::af-
DZ6fY..&&++C1GHH"ItBCyc[D	
 	
    c                     t        d      | j                  | j                  | j                  | j                  fz  }t        |      S )Nz%s%02d$%s%s)r   r+   r*   r)   r9   r   )selfrC   s     r%   	to_stringz_BcryptCommon.to_string   s5    4::t{{DIIt}}"UUT""rI   c                 b    t        d      || j                  | j                  fz  }t        |      S )z5internal helper to prepare config string for backendsz	%s%02d$%s)r   r*   r)   r   )rK   r+   configs      r%   _get_configz_BcryptCommon._get_config   s*    ;5$++tyy"AAV$$rI   c                     t        |t              r|j                  d      }|j                  t              r|d   | j
                  vryt        t        | "  |fi |S )Nascii   T)	
isinstancebytesdecode
startswithIDENT_2Afinal_salt_charssuperr(   needs_update)rB   rC   kwds	__class__s      r%   rZ   z_BcryptCommon.needs_update   sV    
 dE";;w'D??8$b9M9M)M
 ]C5dCdCCrI   c                 f    | j                  |      r| j                  |      j                         S |S )z<helper to normalize hash, correcting any bcrypt padding bits)identifyrH   rL   rB   rC   s     r%   normhashz_BcryptCommon.normhash   s-     <<??4(2244KrI   c                 R    t         t        |          }t        j                  |      S N)rY   r(   _generate_saltr   repair_unused)rB   r)   r\   s     r%   rc   z_BcryptCommon._generate_salt   s%     ]C79%%d++rI   c                     t        t        | 
  |fi |}|J d       t        j                  |      \  }}|rt        dt               |S )Nz!HasSalt didn't generate new salt!zencountered 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)rY   r(   
_norm_saltr   check_repair_unusedr   r	   )rB   r)   r[   changedr\   s       r%   rf   z_BcryptCommon._norm_salt   s[    ]C3DADAD!DD 44T: G #	$
 rI   c                     t         t        |   ||      }t        j                  |      \  }}|rt        dt               |S )N)relaxedzencountered 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)rY   r(   _norm_checksumr   rg   r   r	   )rK   r9   rj   rh   r\   s       r%   rk   z_BcryptCommon._norm_checksum   sK    <Xw<W$88BG #	$
 rI   z9 -- recommend you install one (e.g. 'pip install bcrypt')c                   
 | t         j                     u sJ d       | j                  ry| j                  t        t
        j                  j                  ft        rt        j                  j                  fz  fd}fd}fd

fd}d} |d|      }|t        u rd| _        t        j                  d	       n|st        d
z         |dt               }|t        u rt        dz        |st        dz         |t"                
t"              rJdk(  rt        j                  d       n't%        dz  t
        j                  j&                         d| _        t         j+                  dd      } |d|      }|t        u rd| _        t        j                  d       n(|st        dz         |t.                |t.               t         j+                  dd      }	 |d|	      }|t        u r%d| _        t        j                  d       d| _        y|st        dz        t2        | _         |t2                |t2               d| _        y)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 # $ r	 t         cY S t        j                  j                  $ r# t        j                  d| |d       t         cY S w xY w)z8verify() wrapper which traps 'unknown identifier' errorsz<trapped unexpected response from %r backend: verify(%r, %r):Texc_info)NotImplementedr?   r@   InternalBackendErrorlogdebug)secretrC   backend	err_typesverifys     r%   safe_verifyz:_BcryptCommon._finalize_backend_mixin.<locals>.safe_verify,  sd    &fd++ 	& &%66.. & 		X!64$  @%%&s    A<AAc                     d}| j                  d      dz   }| j                  d      dz   } ||      rt        dd| d       ||      st        d| d	      y
)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   ёrQ   s8   05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcASs8   05$6bNw2HLQYeqHYyBfLMsv/OUcZd0LKP39b87nBw3.S2tVZSqiQX6euz.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+   rt   bug_hashcorrect_hashru   rw   s       r%   assert_lacks_8bit_bugzD_BcryptCommon._finalize_backend_mixin.<locals>.assert_lacks_8bit_bugB  s    0 !F||G,/jjH <<03nnLfh' + RYZ_ab b &,/"QXZ_#`aa 0rI   c                     ddd }| j                  d      dz   } ||      ry| j                  d      dz   } ||      st        d| d	      y
)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)'
            s  01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789N   rQ   s8   04$R1lJ2gkNaoPGdafE.H.16.nVyh2niHsGJhayOHLMiXlI45o8/DU.6Ts8   04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oirz   z wraparound hashF)r{   r|   r}   s       r%   detect_wrap_bugz>_BcryptCommon._finalize_backend_mixin.<locals>.detect_wrap_bugl  sg     '-F||G,/jjHfh' !<<03nnL&,/"W^`e#fggrI   c                 6     |       sy t        d|       )Nz- backend unexpectedly has wraparound bug for )r|   )r+   ru   r   s    r%   assert_lacks_wrap_bugzD_BcryptCommon._finalize_backend_mixin.<locals>.assert_lacks_wrap_bug  s"    "5) V]_deffrI   s;   $2$04$5BJqKfqMQvV7nS.yUguNcuRfMMOXK0xPWavM7pOzjEi5ze5T1k8/Stestz1%r backend lacks $2$ support, enabling workaroundz %s incorrectly rejected $2$ hashz %s lacks support for $2a$ hashesz!%s incorrectly rejected $2a$ hashos_cryptz;%r backend has $2a$ bsd wraparound bug, enabling workaroundzpasslib.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/   r0   z2%r backend lacks $2y$ support, enabling workaroundz!%s incorrectly rejected $2y$ hashr1   z2%r backend lacks $2b$ support, enabling workaroundz!%s incorrectly rejected $2b$ hash)r   _backend_mixin_map_workrounds_initializedrw   r<   r?   r@   MissingBackendError	_bcryptorengine	SaltErrorrp   _lacks_20_supportrr   rs   r|   TEST_HASH_2ArW   r   r
   _has_2a_wraparound_bugreplace_lacks_2y_supportIDENT_2Y_lacks_2b_supportIDENT_2B_fallback_ident)	mixin_clsru   dryrunrx   r   r   test_hash_20resulttest_hash_2ytest_hash_2br   rv   rw   s    `        @@@r%   _finalize_backend_mixinz%_BcryptCommon._finalize_backend_mixin  sS    F55g>> 	@?	@ ,,!!!;!;<	)**4466I	&,(	bT	6	g VV\2^#*.I'III7SAGKLL
 V\2^#AGKLLBWLMM!(+x(j( II[]de  : =DD 66	8
 48	0
 $++D$7V\2^#*.I'IIJGTBWLMM "(+!(+ $++D$7V\2^#*.I'IIJGT -1	) BWLMM(0I%!(+!(+ -1	)rI   c                 R    | j                  || j                  | j                        S )z
        common helper for backends to implement _calc_checksum().
        takes in secret, returns (secret, ident) pair,
        )new)_norm_digest_argsr+   use_defaultsrK   rt   s     r%   _prepare_digest_argsz"_BcryptCommon._prepare_digest_args  s&    
 %%fdjjd>O>O%PPrI   c                    | j                   }t        |t              r|j                  d      }n|r	 |j	                  d       t        j                  |       |r| j                  |       t        |v rt        j                  j                  |       | j                  r"t        |      dk\  r|rt        |d      }n|d d }|t        k(  r	 ||fS |t         k(  r| j"                  r| j$                  }||fS |t&        k(  r| j(                  r| j$                  }||fS |t*        k(  r9| j,                  r)|r|rt/        |d      }nt1        |d      }| j$                  }||fS |t2        k(  rt5        d      t7        d|z        # t
        $ r d}Y Gw xY w)Nutf-8Fr   r6   z.$2x$ hashes not currently supported by passlibzunexpected ident value: %r)_require_valid_utf8_bytesrS   r   r{   rU   UnicodeDecodeErrorr?   validate_secret_check_truncate_policy_BNULLr@   NullPasswordErrorr   lenr   rW   r   r   r   r   r   IDENT_2r   r   r   r;   r|   AssertionError)rB   rt   r+   r   require_valid_utf8_bytess        r%   r   z_BcryptCommon._norm_digest_args  s    $'#@#@ fg&]]7+F%1g& 	6" &&v.
 V&&**3// %%#f+*<' 'vr2 HP u}M h$$
 ++@ u}= h$$ ++4 u}1 g$$ / "4FB!?!.vr!:++ u} h OPP !!=!EFFW & 1 ,1(1s   E< <F
F)F)1__name__
__module____qualname____doc__namesetting_kwdschecksum_sizer   charmapchecksum_charsr   default_identr   rW   r;   r   ident_valuesr   ident_aliasesmin_salt_sizemax_salt_size
salt_charsrX   default_rounds
min_rounds
max_roundsrounds_costtruncate_sizer   r   r   r   r   r   r   classmethodrH   rL   rO   rZ   r`   rc   rf   rk   _no_backend_suggestionr   r   r   __classcell__r\   s   @r%   r(   r(   ^   s|    D@L
 M%%N
 MXx8DLsVWagx!D'8tWh(M %'&MM!!J 
 NJJK
 M $"O % 
 
"#% D D$   , ,  	4 YC CVQ W WrI   r(   c                   "     e Zd ZdZ fdZ xZS )
_NoBackendz
    mixin used before any backend has been loaded.
    contains stubs that force loading of one of the available backends.
    c                 J    | j                          t        t        |   |      S rb   )_stub_requires_backendrY   r   _calc_checksum)rK   rt   r\   s     r%   r   z_NoBackend._calc_checksumN  s#    ##% VT1&99rI   )r   r   r   r   r   r   r   s   @r%   r   r   F  s    : :rI   r   c                   &    e Zd ZdZed        Zd Zy)_BcryptBackendz-
    backend which uses 'bcrypt' package
    c                    t               ry	 dd la	 t        j                  j
                  }t        j                  d|       | j                  ||      S # t        $ r Y yw xY w#  t        j                  dd       d}Y TxY w)NFr   z&(trapped) error reading bcrypt versionTrn   	<unknown>z%detected 'bcrypt' backend, version %r)
r&   r   _bcryptr#   	__about__r"   rr   warningrs   r   )r   r   r   versions       r%   _load_backend_mixinz"_BcryptBackend._load_backend_mixin`  s     	$	"''33G
 			97C00v>>  			"KK@4KP!Gs   A A# 	A A #B c                    | j                  |      \  }}| j                  |      }t        |t              r|j	                  d      }t
        j                  ||      }t        |t              sJ |j                  |      rt        |      t        |      dz   k7  r#t        j                  j                  | ||d      |dd  j                  d      S )NrQ   r-   z`bcrypt` packagesource)r   rO   rS   r   r{   r   hashpwrT   rV   r   r?   r@   CryptBackendErrorrU   rK   rt   r+   rN   rC   s        r%   r   z_BcryptBackend._calc_checksum  s    
 11&9!!%(fg&]]7+F~~ff-$&&v&#d)s6{2~*E&&**4FX*YYCDz  ))rI   Nr   r   r   r   r   r   r    rI   r%   r   r   [  s!     ? ?J*rI   r   c                   &    e Zd ZdZed        Zd Zy)_BcryptorBackendz/
    backend which uses 'bcryptor' package
    c                 r    	 dd l a|st        dt               | j                  ||      S # t        $ r Y yw xY w)Nr   FzqSupport for `bcryptor` is deprecated, and will be removed in Passlib 1.8; Please use `pip install bcrypt` instead)bcryptorr   r#   r   DeprecationWarningr   r   r   r   s      r%   r   z$_BcryptorBackend._load_backend_mixin  sI    	(
  ;<NP 00v>>  		s   * 	66c                 b   | j                  |      \  }}| j                  |      }t        j                  j	                  d      j                  ||      }|j                  |      rt        |      t        |      dz   k7  r#t        j                  j                  | ||d      t        |dd        S )NFr-   zbcryptor libraryr   r   )r   rO   r   r   Enginehash_keyrV   r   r?   r@   r   r   r   s        r%   r   z_BcryptorBackend._calc_checksum  s    
 11&9!!%(&&u-66vvFv&#d)s6{R7G*G&&**4FX*YYT#$Z((rI   Nr   r   rI   r%   r   r     s      ? ?
)rI   r   c                   4    e Zd ZdZdZed        Zd Zd ZeZ	y)_PyBcryptBackendz/
    backend which uses 'pybcrypt' package
    Nc                    t               sy	 dd la|st	        dt
               	 t        j                  j                  }t        j                  d|       t        |      xs d	}|d
k  rft	        d|z  t        j                  j                         | j                  dd l}|j#                         | _        t%        | j&                        | _        | j+                  ||      S # t        $ r Y yw xY w#  t        j                  dd       d}Y xY w)NFr   zrSupport for `py-bcrypt` is deprecated, and will be removed in Passlib 1.8; Please use `pip install bcrypt` insteadz((trapped) error reading pybcrypt versionTrn   r   z'detected 'pybcrypt' backend, version %r)r   r   )r      zapy-bcrypt %s has a major security vulnerability, you should upgrade to py-bcrypt 0.3 immediately.)r&   r   	_pybcryptr#   r   r   r   r"   rr   r   rs   r   r?   r@   r
   
_calc_lock	threadingLockr   _calc_checksum_threadsafer   r   )r   r   r   r   vinfor   s         r%   r   z$_PyBcryptBackend._load_backend_mixin  s     !	&  ;<NP	"''33G 			;WE g&0&6> DFF99; ##+ '0~~'7	$'B9CfCf'gI$00v>>9  			"KKBTKR!Gs   C  C/  	C,+C,/Dc                 h    | j                   5  | j                  |      cd d d        S # 1 sw Y   y xY wrb   )r   _calc_checksum_rawr   s     r%   r   z*_PyBcryptBackend._calc_checksum_threadsafe  s.     __ 	3**62	3 	3 	3s   (1c                 0   | j                  |      \  }}| j                  |      }t        j                  ||      }|j	                  |      rt        |      t        |      dz   k7  r#t        j                  j                  | ||d      t        |dd        S )Nr-   zpybcrypt libraryr   r   )
r   rO   r   r   rV   r   r?   r@   r   r   r   s        r%   r   z#_PyBcryptBackend._calc_checksum_raw  s     11&9!!%(/v&#d)s6{R7G*G&&**4FX*YYT#$Z((rI   )
r   r   r   r   r   r   r   r   r   r   r   rI   r%   r   r     s2    
 J$? $?L3) (NrI   r   c                   ,    e Zd ZdZe Zed        Zd Zy)_OsCryptBackendz0
    backend which uses :func:`crypt.crypt`
    c                 H    t        dt              sy| j                  ||      S )Nr   F)r   r   r   r   s      r%   r   z#_OsCryptBackend._load_backend_mixin  s"    &,/00v>>rI   c                 ^   | j                  |      \  }}| j                  |      }t        ||      }|Q|j                  |      rt	        |      t	        |      dz   k7  r!t
        j                  j                  | ||      |dd  S t        r"t        |t              r	 |j                  d       t
        j                  j                  }t
        j                  j!                  d ||      d ||      d      # t        $ r* t        t
        j                  j                  d      d       w xY w)Nr-   r   r   zpython3 crypt.crypt() ony supports bytes passwords using UTF8; passlib recommends running `pip install bcrypt` for general bcrypt support.z|crypt.crypt() failed for unknown reason; passlib recommends running `pip install bcrypt` for general bcrypt support.(config=z	, secret=))r   rO   r   rV   r   r?   r@   r   r   rS   rT   rU   r   r   PasswordValueErrordebug_only_reprrq   )rK   rt   r+   rN   rC   r   s         r%   r   z_OsCryptBackend._calc_checksum  s   
 11&9!!%(&&)??6*c$i3v;;K.Kff..tVTBB: :fe,g&* &&00ff)) )8(?QWAXZ 	+ &  !:!:b"  s   C9 93D,N)	r   r   r   r   r   r   r   r   r   r   rI   r%   r   r     s)     %8 7? ?
7rI   r   c                   &    e Zd ZdZed        Zd Zy)_BuiltinBackendzA
    backend which uses passlib's pure-python implementation
    c                     ddl m}  |t        j                  j	                  d            st
        j                  d       yddlma	 | j                  ||      S )Nr   )as_boolPASSLIB_BUILTIN_BCRYPTz@bcrypt 'builtin' backend not enabled via $PASSLIB_BUILTIN_BCRYPTF)
raw_bcrypt)passlib.utilsr   osenvirongetrr   rs   passlib.crypto._blowfishr  _builtin_bcryptr   )r   r   r   r   s       r%   r   z#_BuiltinBackend._load_backend_mixinS  sA    )rzz~~&>?@IIXYJ00v>>rI   c                     | j                  |      \  }}t        ||dd | j                  j                  d      | j                        }|j                  d      S )N   rQ   )r   r  r)   r{   r*   rU   )rK   rt   r+   rG   s       r%   r   z_BuiltinBackend._calc_checksum]  sR    11&9feAbk"ii..w7Fzz'""rI   Nr   r   rI   r%   r   r   O  s      ? ?#rI   r   c                   *    e Zd ZdZdZdZeeee	e
edZy)r   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.
    )r   pybcryptr   r   builtinT)Nr   r  r   r   r  N)r   r   r   r   backends_backend_mixin_targetr   r   r   r   r   r   r   r   rI   r%   r   r   f  s5    @V IH !  $$#"rI   r8   c                   V    e Zd ZdZ ed ej                  D              ZdZed        Z	y)_wrapped_bcryptz
    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              #   *   K   | ]  }|d vs|  yw))r,   Nr   ).0elems     r%   	<genexpr>z_wrapped_bcrypt.<genexpr>  s     `$M_A_`s   	Nc                      y rb   r   )rB   rt   s     r%   r   z&_wrapped_bcrypt._check_truncate_policy  s     	rI   )
r   r   r   r   tupler   r   r   r   r   r   rI   r%   r  r    s8    
 `&*=*=``LM&  rI   r  c                   6    e Zd ZdZd ZeefZ d e      ZeZ	 e
ddg      ZdZed fd	       Z ed      Z ej$                  d      Z ej$                  d      Zed	        Zed
        Z ed      Z ed      Zd Zd fd	Zed        Z fdZ fdZ xZS )bcrypt_sha256a  
    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                 d     t         fdt        j                  j                         D              S )Nc              3   0   K   | ]  }|d    v r|  yw)r	  Nr   )r  itemr   s     r%   r  z)bcrypt_sha256.<lambda>.<locals>.<genexpr>  s&      /K26q'\2I 04 /Ks   )dictr   r   items)r   s   `r%   <lambda>zbcrypt_sha256.<lambda>  s*    $ /K@T@T@Z@Z@\ /K +K rI   r	     c                     t        t        | 
  di |}||j                  |      |_        |j
                  }|j                  dkD  r$|t        k7  rt        d|d|j                        |S )Nr	  zbcrypt z  hashes not allowed for version r   )rY   r  using_norm_versionr   r   r   r<   )rB   r   r[   subclsr+   r\   s        r%   r"  zbcrypt_sha256.using,  sm    }c0848#11':FN$$>>A%8"3#V^^5 6 6rI   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                 h    t        j                  |      }|sy|j                  | j                        S )NF)r?   to_unicode_for_identifyrV   prefixr_   s     r%   r^   zbcrypt_sha256.identifya  s+    ))$/szz**rI   c           	         t        |dd      }|j                  | j                        st        j                  j                  |       | j                  j                  |      }|r>t        |j                  d            }|dk  r^t        j                  j                  |       | j                  j                  |      }|rd}nt        j                  j                  |       |j                  d      }|j                  t        j                        r2|t        j                  k7  rt        j                  j                  |        | ||j                  d      t        |      |j                  d      |j                  d	      
      S )NrQ   rC   r   r   r	  r*   typer)   digest)r   r+   r*   r)   r9   )r   rV   r'  r?   r@   InvalidHashError_v2_hash_rematchr>   grouprA   _v1_hash_re_UZEROZeroPaddedRoundsError)rB   rC   mr   r*   s        r%   rH   zbcrypt_sha256.from_stringh  s%   $0szz*&&))#..OO!!$'!''),-G{ff//44%%d+Aff//44"RYY'Fbii,?&&..s33''&/v;WWX&
 	
rI   z"$bcrypt-sha256$v=2,t=%s,r=%d$%s$%sz$bcrypt-sha256$%s,%d$%s$%sc                     | j                   dk(  r| j                  }n| j                  }|| j                  j	                  t
              | j                  | j                  | j                  fz  }t        |      S )Nr	  )
r   _v1_template_v2_templater+   strip_UDOLLARr*   r)   r9   r   )rK   templaterC   s      r%   rL   zbcrypt_sha256.to_string  s]    <<1((H((H4::++H5t{{DIIt}}]]T""rI   c                 \    || j                  |      | _        t        t        |   di | y )Nr   )r#  r   rY   r  __init__)rK   r   r[   r\   s      r%   r:  zbcrypt_sha256.__init__  s-    --g6DLmT+3d3rI   c                 V    || j                   vrt        | j                  d|      |S )Nz": unknown or unsupported version: )_supported_versionsr<   r   )rB   r   s     r%   r#  zbcrypt_sha256._norm_version  s*    #111SZ[\\rI   c                 f   t        |t              r|j                  d      }| j                  dk(  rt	        |      j                         }nI| j                  }|d   | j                  vrt        d       t        d|j                  d            |      }t        |      }t        t        | 7  |      S )Nr   r	  r
  zinvalid salt stringr   rQ   )rS   r   r{   r   r   r*  r)   rX   r<   r   r   rY   r  r   )rK   rt   r*  r)   keyr\   s        r%   r   zbcrypt_sha256._calc_checksum  s     fg&]]7+F<<1 F^**,F 99DBxt444 !!677A\(DKK,@A&IF  ]D8==rI   c                 p    | j                   t        |       j                   k  ryt        t        |   di |S )NTr   )r   r)  rY   r  _calc_needs_update)rK   r[   r\   s     r%   r@  z bcrypt_sha256._calc_needs_update  s1    <<$t*,,,]D<DtDDrI   rb   )r   r   r   r   r   rW   r   r   r   r   setr<  r   r   r"  r   r'  recompiler,  r/  r^   rH   r5  r4  rL   r:  r#  r   r@  r   r   s   @r%   r  r    s   8 D h'LKLXZMM q!f+ G  6  !F "** 	 	K "**  K + + 
 
4 9:L12L#4  %>VE ErI   r  )Nr   
__future__r   r   base64r   hashlibr   r  rB  logging	getLoggerr   rr   warningsr   r   r   r   r  passlib.crypto.digestr   passlib.excr	   r
   r   r  r   r   r   r   r   r   r   r   r   r   r   passlib.utils.binaryr   passlib.utils.compatr   r   r   r   r   r   r   passlib.utils.handlersutilshandlersr?   __all__r   rW   r;   r   r   r   r   r&   SubclassBackendMixinTruncateMixinHasManyIdents	HasRoundsHasSaltGenericHandlerr(   r   r   r   r   r   r   r   r7  r  r  r   rI   r%   <module>rX     s   7   	 	 'g''1 
		 . X XQ Q Q Q * < Z Z # #  E(V9V9V9V9	 N"NcB++R-=-=r?O?OLL"**b.?.?cP: :*8*] 8*z)} )HC(} C(PFm FV#m #.YZ YD S6f FdEO dErI   