
    gX                        S r SSKr\R                  " \5      rSSKJrJrJrJ	r	  SSK
JrJr  SSKJrJrJrJr  SSKJrJr  SSKJs  Jr  S/r " S S\R4                  \R6                  \R8                  \R:                  5      rg)	z:passlib.handlers.scram - hash for SCRAM credential storage    N)consteqsaslprepto_native_str
splitcomma)ab64_decodeab64_encode)bascii_to_str	iteritemsunative_string_types)pbkdf2_hmacnorm_hash_namescramc                     ^  \ rS rSrSrS rSr\" S5      rSr	Sr
SrSrS	rS
r/ SQr/ SQrSr\S 5       r\SS j5       r\S 5       r\S 5       rS r\SU 4S jj5       rSU 4S jjrSS jr\S 5       rU 4S jrSS jr\SS j5       rSrU =r $ )r      a  This class provides a format for storing SCRAM passwords, and follows
the :ref:`password-hash-api`.

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

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

:type salt: bytes
:param salt:
    Optional salt bytes.
    If specified, the length must be between 0-1024 bytes.
    If not specified, a 12 byte salt will be autogenerated
    (this is recommended).

:type salt_size: int
:param salt_size:
    Optional number of bytes to use when autogenerating new salts.
    Defaults to 12 bytes, but can be any value between 0 and 1024.

:type rounds: int
:param rounds:
    Optional number of rounds to use.
    Defaults to 100000, but must be within ``range(1,1<<32)``.

:type algs: list of strings
:param algs:
    Specify list of digest algorithms to use.

    By default each scram hash will contain digests for SHA-1,
    SHA-256, and SHA-512. This can be overridden by specify either be a
    list such as ``["sha-1", "sha-256"]``, or a comma-separated string
    such as ``"sha-1, sha-256"``. Names are case insensitive, and may
    use :mod:`!hashlib` or `IANA <http://www.iana.org/assignments/hash-function-text-names>`_
    hash names.

: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

In addition to the standard :ref:`password-hash-api` methods,
this class also provides the following methods for manipulating Passlib
scram hashes in ways useful for pluging into a SCRAM protocol stack:

.. automethod:: extract_digest_info
.. automethod:: extract_digest_algs
.. automethod:: derive_digest
)salt	salt_sizeroundsalgs$scram$   i   i    l    linear)sha-1sha-256sha-512)r   r   zsha-224zsha-384r   Nc                     [        US5      nU R                  U5      nUR                  nU(       d  [        S5      eUR                  UR
                  XB   4$ )aH  return (salt, rounds, digest) for specific hash algorithm.

:type hash: str
:arg hash:
    :class:`!scram` hash stored for desired user

:type alg: str
:arg alg:
    Name of digest algorithm (e.g. ``"sha-1"``) requested by client.

    This value is run through :func:`~passlib.crypto.digest.norm_hash_name`,
    so it is case-insensitive, and can be the raw SCRAM
    mechanism name (e.g. ``"SCRAM-SHA-1"``), the IANA name,
    or the hashlib name.

:raises KeyError:
    If the hash does not contain an entry for the requested digest
    algorithm.

:returns:
    A tuple containing ``(salt, rounds, digest)``,
    where *digest* matches the raw bytes returned by
    SCRAM's :func:`Hi` function for the stored password,
    the provided *salt*, and the iteration count (*rounds*).
    *salt* and *digest* are both raw (unencoded) bytes.
ianazscram hash contains no digests)r   from_stringchecksum
ValueErrorr   r   )clshashalgselfchkmaps        O/home/matz/Project1/venv/lib/python3.13/site-packages/passlib/handlers/scram.pyextract_digest_infoscram.extract_digest_info|   sM    > S&)t$=>>yy$++v{22    c                     U R                  U5      R                  nUS:X  a  U$ U Vs/ s H  n[        XB5      PM     sn$ s  snf )a  Return names of all algorithms stored in a given hash.

:type hash: str
:arg hash:
    The :class:`!scram` hash to parse

:type format: str
:param format:
    This changes the naming convention used by the
    returned algorithm names. By default the names
    are IANA-compatible; possible values are ``"iana"`` or ``"hashlib"``.

:returns:
    Returns a list of digest algorithms; e.g. ``["sha-1"]``
r   )r   r   r   )r"   r#   formatr   r$   s        r'   extract_digest_algsscram.extract_digest_algs   sB    ( t$))VK;?@4CN3/4@@@s   A c                 z    [        U[        5      (       a  UR                  S5      n[        U[	        U5      X#5      $ )a  helper to create SaltedPassword digest for SCRAM.

This performs the step in the SCRAM protocol described as::

    SaltedPassword  := Hi(Normalize(password), salt, i)

:type password: unicode or utf-8 bytes
:arg password: password to run through digest

:type salt: bytes
:arg salt: raw salt data

:type rounds: int
:arg rounds: number of iterations.

:type alg: str
:arg alg: name of digest to use (e.g. ``"sha-1"``).

:returns:
    raw bytes of ``SaltedPassword``
zutf-8)
isinstancebytesdecoder   r   )r"   passwordr   r   r$   s        r'   derive_digestscram.derive_digest   s5    . h&&w/H 3 2DAAr*   c                 |   [        USS5      nUR                  S5      (       d  [        R                  R	                  U 5      eUSS  R                  S5      n[        U5      S:w  a  [        R                  R                  U 5      eUu  p4n[        U5      nU[        U5      :w  a  [        R                  R                  U 5      e [        UR                  S5      5      nU(       d  [        R                  R                  U 5      eSU;   aM  S n0 n	UR                  S5       H3  n
U
R                  S5      u  p [        UR                  S5      5      X'   M5     OUnS n	U " UUU	US	9$ ! [         a     [        R                  R                  U 5      ef = f! [         a     [        R                  R                  U 5      ef = f)
Nasciir#   r      $   =,)r   r   r    r   )r   
startswithuhexcInvalidHashErrorsplitlenMalformedHashErrorintstrr   encode	TypeError)r"   r#   parts
rounds_strsalt_strchk_strr   r   r   r&   pairr$   digests                r'   r   scram.from_string   s   T7F3y))&&))#..QRs#u:?&&++C00(-%
g ZV$&&++C00	1xw78D
 &&++C00G^DFc*"jjo9"-fmmG.D"EFK + DF 	
 	
/  	1&&++C00	1 ! 9&&33C889s   E$ 6F$*F*F;c                    ^ [        [        U R                  5      5      nU R                  mSR	                  U4S jU R
                   5       5      nSU R                  X4-  $ )Nr<   c           	   3   `   >#    U  H#  nU< S [        [        TU   5      5      < 3v   M%     g7f)r;   N)r	   r   ).0r$   r&   s     r'   	<genexpr>"scram.to_string.<locals>.<genexpr>  s+      
  M+fSk*BCD s   +.z$scram$%d$%s$%s)r	   r   r   r    joinr   r   )r%   r   rK   r&   s      @r'   	to_stringscram.to_string  sT    [34(( 
yy
 
 !DKK#???r*   c                 v   > Ub  Ub   eUn[         [        U ]
  " S0 UD6nUb  U R                  U5      Ul        U$ )N )superr   using
_norm_algsdefault_algs)r"   r\   r   kwdssubcls	__class__s        r'   rZ   scram.using  sP     '''L uc(040 #"%..">Fr*   c                   > [         [        U ]
  " S0 UD6  U R                  nUb   Ub  [	        S5      eU R                  U5      nOuUb   U R                  UR                  5       5      nORU R                  (       a6  [        U R                  5      nU R                  U5      U:X  d   SU< 35       eO[        S5      eXl        g )Nz+checksum & algs kwds are mutually exclusivezinvalid default algs: zno algs list specifiedrX   )rY   r   __init__r    RuntimeErrorr[   keysuse_defaultslistr\   rG   r   )r%   r   r]   
digest_mapr_   s       r'   rb   scram.__init__+  s    eT#+d+ ]]
%"#PQQ??4(D#??:??#45D))*D??4(D0VPT2VV0455	r*   c                    [        U[        5      (       d!  [        R                  R	                  USS5      e[        U5       Hx  u  p4U[        US5      :w  a  [        SU< 35      e[        U5      S:  a  [        SU< 35      e[        U[        5      (       a  MY  [        R                  R	                  USS5      e   S	U;  a  [        S
5      eU$ )Ndictr    r   z(malformed algorithm name in scram hash: 	   z.SCRAM limits algorithm names to 9 characters: z	raw bytesdigestsr   -sha-1 must be in algorithm list of scram hash)
r0   rj   r>   r?   ExpectedTypeErrorr
   r   r!   rB   r1   )r%   r    relaxedr$   rM   s        r'   _norm_checksumscram._norm_checksum>  s    (D))&&**8VZHH$X.KCnS&11 "%"( ) )3x!| 7:"= > >fe,,ff..v{INN / ("LMMr*   c                     [        U[        5      (       a  [        U5      n[        S U 5       5      n[	        S U 5       5      (       a  [        S5      eSU;  a  [        S5      eU$ )znormalize algs parameterc              3   :   #    U  H  n[        US 5      v   M     g7f)r   N)r   rQ   r$   s     r'   rR   #scram._norm_algs.<locals>.<genexpr>U  s     BTcnS&11Ts   c              3   >   #    U  H  n[        U5      S :  v   M     g7f)rk   N)rB   rt   s     r'   rR   ru   V  s     *Tcs3xzTs   z-SCRAM limits alg names to max of 9 charactersr   rm   )r0   r   r   sortedanyr!   )r"   r   s     r'   r[   scram._norm_algsP  sb     d/00d#DBTBB*T***LMM$LMMr*   c                    > [        U R                  5      R                  U R                  5      (       d  g[        [
        U ]  " S0 UD6$ )NTrX   )setr   
issupersetr\   rY   r   _calc_needs_update)r%   r]   r_   s     r'   r}   scram._calc_needs_update`  s>     499~(():):;; UD4<t<<r*   c                    ^^^^ U R                   mU R                  mU R                  mU(       a  T" TTTU5      $ [        UUUU4S jU R                   5       5      $ )Nc              3   >   >#    U  H  nUT" TTTU5      4v   M     g 7fNrX   )rQ   r$   r#   r   r   secrets     r'   rR   'scram._calc_checksum.<locals>.<genexpr>v  s(      $C d6456$s   )r   r   r4   rj   r   )r%   r   r$   r#   r   r   s    ` @@@r'   _calc_checksumscram._calc_checksumm  sT    yy!!fc22  99  r*   c                    [         R                  " U5        U R                  U5      nUR                  nU(       d(  [	        SU R
                  < SU R
                  < S35      eU(       a  S=pg[        U5       Hm  u  pUR                  X5      n
[        U	5      [        U
5      :w  a)  [	        SU< S[        U	5      < S[        U
5      < 35      e[        X5      (       a  SnMk  SnMo     U(       a  U(       a  [	        S	5      eU$ UR                   H)  nX;   d  M
  UR                  X5      n
[        XU   5      s  $    [        S
5      e)Nz	expected z hash, got z config string insteadFz
mis-sized z digest in scram hash: z != Tz4scram hash verified inconsistently, may be corruptedzsha-1 digest not found!)r>   validate_secretr   r    r!   namer
   r   rB   r   _verify_algsAssertionError)r"   r   r#   fullr%   r&   correctfailedr$   rM   others              r'   verifyscram.verify{  s&   
6"t$!hh2 3 3 $$G(0++F8
 v;#e*,$(+S[#e*&F G G5))"G!F  1 6  "4 5 5  ((= //<E"5+66 ) !!:;;r*   )r   )r   )NNr   )F)!__name__
__module____qualname____firstlineno____doc__r   setting_kwdsr   identdefault_salt_sizemax_salt_sizedefault_rounds
min_rounds
max_roundsrounds_costr\   r   r   classmethodr(   r-   r4   r   rU   rZ   rb   rp   r[   r}   r   r   __static_attributes____classcell__)r_   s   @r'   r   r      s   4B D:LiLE M NJJK
 3L IL D
 #3 #3J A A2 B B@ -
 -
^@  "&$ 
 
= (< (<r*   )r   logging	getLoggerr   logpasslib.utilsr   r   r   r   passlib.utils.binaryr   r   passlib.utils.compatr	   r
   r   r   passlib.crypto.digestr   r   passlib.utils.handlersutilshandlersr>   __all__	HasRounds
HasRawSaltHasRawChecksumGenericHandlerr   rX   r*   r'   <module>r      sk    @
 g''1 G F 9 Q Q = # # N<BLL"--):):B<M<M N<r*   