
     hX                        d Z ddlZ ej                  e      ZddlmZmZmZm	Z	 ddl
mZmZ ddlmZmZmZmZ ddlmZmZ ddlmc mZ dgZ G d dej4                  ej6                  ej8                  ej:                        Zy)	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                       e Zd ZdZd ZdZ ed      ZdZdZ	dZ
dZdZd	Zg d
Zg dZdZed        Zedd       Zed        Zed        Zd Zed fd	       Zd fd	ZddZed        Z fdZddZedd       Z xZS )r   aZ  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                     t        |d      }| j                  |      }|j                  }|st        d      |j                  |j
                  ||   fS )a  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        X/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/passlib/handlers/scram.pyextract_digest_infozscram.extract_digest_info|   sO    > S&)t$=>>yy$++vc{22    c                     | j                  |      j                  }|dk(  r|S |D cg c]  }t        ||       c}S c c}w )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_algszscram.extract_digest_algs   s@    ( t$))VK;?@CN3/@@@s   =c                 r    t        |t              r|j                  d      }t        |t	        |      ||      S )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_digestzscram.derive_digest   s4    . h&w/H 3 2D&AAr(   c                 d   t        |dd      }|j                  d      st        j                  j	                  |       |dd  j                  d      }t        |      dk7  rt        j                  j                  |       |\  }}}t        |      }|t        |      k7  rt        j                  j                  |       	 t        |j                  d            }|st        j                  j                  |       d|v rMd }i }	|j                  d      D ]4  }
|
j                  d      \  }}	 t        |j                  d            |	|<   6 n|}d }	 | |||	|	      S # t        $ r  t        j                  j                  |       w xY w# t        $ r  t        j                  j                  |       w xY w)
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   zscram.from_string   s   T7F3y)&&))#..QRs#u:?&&++C00(-%
Hg ZV$&&++C00	1xw78D
 &&++C00G^DFc* 9"jjoV9"-fmmG.D"EF3K9 DF 	
 	
/  	1&&++C00	1 ! 9&&33C889s   >E *F)F)F/c                     t        t        | j                              }| j                  dj	                  fd| j
                  D              }d| j                  ||fz  S )Nr8   c           	   3   V   K   | ]   }|d t        t        |                " yw)r7   N)r	   r   ).0r#   r%   s     r&   	<genexpr>z"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   rG   r%   s      @r&   	to_stringzscram.to_string  sV    [34(( 
yy
 
 !DKKw#???r(   c                 n    ||J |}t        t        | 
  di |}|| j                  |      |_        |S )N )superr   using
_norm_algsdefault_algs)r!   rU   r   kwdssubcls	__class__s        r&   rS   zscram.using  sM     ''L uc(040 #"%..">Fr(   c                    t        t        | 
  di | | j                  }|&|t	        d      | j                  |      }|| _        y |'| j                  |j                               }|| _        y | j                  r3t        | j                        }| j                  |      |k(  sJ d|       t        d      || _        y )Nz+checksum & algs kwds are mutually exclusivezinvalid default algs: zno algs list specifiedrQ   )rR   r   __init__r   RuntimeErrorrT   keysuse_defaultslistrU   rC   r   )r$   r   rV   
digest_maprX   s       r&   rZ   zscram.__init__+  s    eT#+d+ ]]
%"#PQQ??4(D 	 #??:??#45D 	 ))*D??4(D0VPT2VV455	r(   c                    t        |t              s!t        j                  j	                  |dd      t        |      D ]o  \  }}|t        |d      k7  rt        d|      t        |      dkD  rt        d|      t        |t              rPt        j                  j	                  |dd       d	|vrt        d
      |S )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)
r-   ra   r:   r;   ExpectedTypeErrorr
   r   r    r>   r.   )r$   r   relaxedr#   rI   s        r&   _norm_checksumzscram._norm_checksum>  s    (D)&&**8VZHH$X. 	OKCnS&11 "%"( ) )3x!| 7:"= > >fe,ff..v{INN	O ("LMMr(   c                     t        |t              rt        |      }t        d |D              }t	        d |D              rt        d      d|vrt        d      |S )znormalize algs parameterc              3   4   K   | ]  }t        |d         yw)r   N)r   rL   r#   s     r&   rM   z#scram._norm_algs.<locals>.<genexpr>U  s     BcnS&1Bs   c              3   8   K   | ]  }t        |      d kD    yw)rb   N)r>   rj   s     r&   rM   z#scram._norm_algs.<locals>.<genexpr>V  s     *cs3xz*s   z-SCRAM limits alg names to max of 9 charactersr   rd   )r-   r   r   sortedanyr    )r!   r   s     r&   rT   zscram._norm_algsP  s\     d/0d#DBTBB*T**LMM$LMMr(   c                     t        | j                        j                  | j                        syt	        t
        |   di |S )NTrQ   )setr   
issupersetrU   rR   r   _calc_needs_update)r$   rV   rX   s     r&   rq   zscram._calc_needs_update`  s;     499~(():):; UD4<t<<r(   c                     | j                   | j                  | j                  |r |      S t        fd| j                  D              S )Nc              3   8   K   | ]  }| |      f  y wNrQ   )rL   r#   r"   r   r   secrets     r&   rM   z'scram._calc_checksum.<locals>.<genexpr>v  s)       d6456s   )r   r   r1   ra   r   )r$   ru   r#   r"   r   r   s    ` @@@r&   _calc_checksumzscram._calc_checksumm  sT    yy!!fc22  99  r(   c                 P   t        j                  |       | j                  |      }|j                  }|s&t	        d| j
                  d| j
                  d      |rdx}}t        |      D ]e  \  }}	|j                  ||      }
t        |	      t        |
      k7  r&t	        d|dt        |	      dt        |
            t        |
|	      rd}dd}g |r|rt	        d	      |S |j                  D ])  }||v s|j                  ||      }
t        |
||         c S  t        d
      )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
   rv   r>   r   _verify_algsAssertionError)r!   ru   r"   fullr$   r%   correctfailedr#   rI   others              r&   verifyzscram.verify{  s;   
6"t$!hh2 3 3 $$Gf(0 "V++FC8
 v;#e*,$(+S[#e*&F G G5&)"G!F" 6  "4 5 5  (( 7&= //<E"5&+667 !!:;;r(   )r   )NNrt   )F)__name__
__module____qualname____doc__ry   setting_kwdsr   identdefault_salt_sizemax_salt_sizedefault_rounds
min_rounds
max_roundsrounds_costrU   rz   r   classmethodr'   r+   r1   r   rO   rS   rZ   rg   rT   rq   rv   r   __classcell__)rX   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   rQ   r(   r&   <module>r      sn    @
 'g''1 G F 9 Q Q = # # N<BLL"--):):B<M<M N<r(   