U
    h(U                     @   s   d Z ddlZddlZeeZddlmZmZm	Z	m
Z
 ddlmZ ddlmZmZmZmZ ddlm  mZ ddgZdZd	Zd
ZdZdddZedZedZedZG dd dejej ej!ej"Z#G dd de#Z$G dd de#Z%dS )z9passlib.handlers.sha2_crypt - SHA256-Crypt / SHA512-Crypt    N)
safe_crypt
test_cryptrepeat_string
to_unicode)h64)byte_elem_valueuuascii_to_strunicodesha512_cryptsha256_crypt    ))r            r   r   )r      r   r   r   r   )   r   r   r   )r   r   r   r   r   )r   r   r   r   )r   r   r   r   r   )    
   r      r      r               r      r      r                                          	         )@*   r   r   r   +   r   r   r   ,   -   r   r   r   .   r    r"   r   /   0   r'   r$   r&   1   r)   r+   r(   2   3   r.   r-   r   4   r/       r   5   6   !   r   r   7   "   #   r   8   9   $   r!   r#   :   %   &   r%   ;   <   '   r*   r,   =   (   )   r   >   ?   Fc                    s  t | tr| d} t | ts"tt| kr>tj|r8t	nt
t| }d|  krZdksdn tdt |tsvtd|d}t|}|dk std|rtj}t}n
tj}t}|| | |   }|| | }	|	j}
|
t|| |}|r|
|d	@ r|n|  |d	L }q|	 }|d
k r8t|| |  |}n>|| }|j}|d	 }|rh||  |d	8 }qNt| |}t||kst||dt|d    d| }t||kstd|| }|| }||||| || || g  fddtD }|}t|d\}}|rP|D ]&\}}|||||    }q|d	8 }q|r|d	? }|d| D ]&\}}|||||    }qj|d	@ r|||| d   }t||dS )a  perform raw sha256-crypt / sha512-crypt

    this function provides a pure-python implementation of the internals
    for the SHA256-Crypt and SHA512-Crypt algorithms; it doesn't
    handle any of the parsing/validation of the hash strings themselves.

    :arg pwd: password chars/bytes to hash
    :arg salt: salt chars to use
    :arg rounds: linear rounds cost
    :arg use_512: use sha512-crypt instead of sha256-crypt mode

    :returns:
        encoded checksum chars
    zutf-8  ɚ;zinvalid roundszsalt not unicodeasciir%   zsalt too larger   `   r#   r   Nzsalt_len somehow > hash_len!c                    s    g | ]\}} |  | fqS  rT   ).0evenoddZpermsrT   A./venv/lib/python3.8/site-packages/passlib/handlers/sha2_crypt.py
<listcomp>   s     z#_raw_sha2_crypt.<locals>.<listcomp>r0   )
isinstancer
   encodebytesAssertionError_BNULLuhexcZNullPasswordErrorr   r   lenhashlibZsha512_512_transpose_mapZsha256_256_transpose_mapZdigestupdater   r   _c_digest_offsetsdivmodr   Zencode_transposed_bytesdecode)pwdsaltroundsZuse_512Zpwd_lenZsalt_lenZ
hash_constZtranspose_mapZdbZa_ctxZa_ctx_updateidaZdpZtmp_ctxZtmp_ctx_updateZdsZdp_dpZdp_dsdataZdcZblockstailrV   rW   ZpairsrT   rX   rY   _raw_sha2_crypt8   sl    !




$.  
rq   zrounds=$0c                       s   e Zd ZdZdZejZdZejZ	dZ
dZdZdZdZdZd fd	d
	Zdd Zdd Zedd Zdd ZdZdZedd Zdd Zedd Zdd Z  ZS )_SHA2_CommonzBclass containing common code shared by sha256_crypt & sha512_crypt)rk   rl   implicit_roundsZ	salt_sizer#   rP   rQ   ZlinearFNc                    s4   t t| jf | |d kr*| jo(| jdk}|| _d S )N  )superrt   __init__Zuse_defaultsrl   ru   )selfru   kwds	__class__rT   rY   rx     s    z_SHA2_Common.__init__c                 C   s   | j || jd kdS N)Zrelaxed)Z
_norm_saltchecksum)ry   rk   rT   rT   rY   _parse_salt  s    z_SHA2_Common._parse_saltc                 C   s   | j || jd kdS r}   )Z_norm_roundsr~   )ry   rl   rT   rT   rY   _parse_rounds#  s    z_SHA2_Common._parse_roundsc                 C   s   t |dd}| j}||s(tj| t|dks8t|dd  t	}|d t
rtt
dksht|ddd  }|tr|tkrtj| t|}d}nd}d}t|d	kr|\}}n&t|d
kr|d }d }ntj| | |||pd |dS )NrR   hashr   r   r&   Frv   Tr   r   )rl   rk   r~   ru   )r   ident
startswithr`   ra   ZInvalidHashErrorrb   r^   split_UDOLLAR_UROUNDSpop_UZEROZZeroPaddedRoundsErrorintZMalformedHashError)clsr   r   partsrl   ru   rk   ZchkrT   rT   rY   from_string'  s6    	

z_SHA2_Common.from_stringc                 C   s^   | j dkr2| jr2td| j| j| jp*tdf }n$td| j| j | j| jpPtdf }t|S )Nrv   z%s%s$%s z%srounds=%d$%s$%s)rl   ru   r   r   rk   r~   r	   )ry   r   rT   rT   rY   	to_stringT  s     z_SHA2_Common.to_string)Zos_cryptZbuiltinc                 C   s"   t | j r| | j dS dS d S )NTF)r   
_test_hash_set_calc_checksum_backend_calc_checksum_os_cryptr   rT   rT   rY   _load_backend_os_crypti  s    
z#_SHA2_Common._load_backend_os_cryptc                 C   sf   |   }t||}|d kr$| |S | j}|| jrH|| d  tkrXtj	| |||| d  S )Nr   )
r   r   _calc_checksum_builtinchecksum_sizer   r   r   r`   ra   ZCryptBackendError)ry   secretZconfigr   csrT   rT   rY   r   q  s    

z$_SHA2_Common._calc_checksum_os_cryptc                 C   s   |  | j dS )NT)r   r   r   rT   rT   rY   _load_backend_builtin  s    z"_SHA2_Common._load_backend_builtinc                 C   s   t || j| j| jS )N)rq   rk   rl   _cdb_use_512)ry   r   rT   rT   rY   r     s    z#_SHA2_Common._calc_checksum_builtin)N)__name__
__module____qualname____doc__Zsetting_kwdsr`   ZHASH64_CHARSZchecksum_charsZmax_salt_sizeZ
salt_charsZ
min_roundsZ
max_roundsZrounds_costr   Z_rounds_prefixru   rx   r   r   classmethodr   r   Zbackendsr   r   r   r   r   __classcell__rT   rT   r{   rY   rt      s2   
,

rt   c                   @   s(   e Zd ZdZd ZedZdZdZdZ	dS )r   aK  This class implements the SHA256-Crypt password hash, 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: str
    :param salt:
        Optional salt string.
        If not specified, one will be autogenerated (this is recommended).
        If specified, it must be 0-16 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :type rounds: int
    :param rounds:
        Optional number of rounds to use.
        Defaults to 535000, must be between 1000 and 999999999, inclusive.

        .. note::
            per the official specification, when the rounds parameter is set to 5000,
            it may be omitted from the hash string.

    :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

    ..
        commented out, currently only supported by :meth:`hash`, and not via :meth:`using`:

        :type implicit_rounds: bool
        :param implicit_rounds:
            this is an internal option which generally doesn't need to be touched.

            this flag determines whether the hash should omit the rounds parameter
            when encoding it to a string; this is only permitted by the spec for rounds=5000,
            and the flag is ignored otherwise. the spec requires the two different
            encodings be preserved as they are, instead of normalizing them.
    z$5$r1   i) )testz?$5$rounds=1000$test$QmQADEXMG8POI5WDsaeho0P36yK3Tcrgboabng6bkb/N)
r   r   r   r   namer   r   r   default_roundsr   rT   rT   rT   rY   r     s   .c                   @   s,   e Zd ZdZd ZedZdZdZdZ	dZ
dS )r   aK  This class implements the SHA512-Crypt password hash, 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: str
    :param salt:
        Optional salt string.
        If not specified, one will be autogenerated (this is recommended).
        If specified, it must be 0-16 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :type rounds: int
    :param rounds:
        Optional number of rounds to use.
        Defaults to 656000, must be between 1000 and 999999999, inclusive.

        .. note::
            per the official specification, when the rounds parameter is set to 5000,
            it may be omitted from the hash string.

    :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

    ..
        commented out, currently only supported by :meth:`hash`, and not via :meth:`using`:

        :type implicit_rounds: bool
        :param implicit_rounds:
            this is an internal option which generally doesn't need to be touched.

            this flag determines whether the hash should omit the rounds parameter
            when encoding it to a string; this is only permitted by the spec for rounds=5000,
            and the flag is ignored otherwise. the spec requires the two different
            encodings be preserved as they are, instead of normalizing them.
    z$6$V   Ti
 )r   zj$6$rounds=1000$test$2M/Lx6MtobqjLjobw0Wmo4Q5OFx5nVLJvmgseatA6oMnyWeBdRDx4DU.1H3eGmse6pgsOgDisWBGI5c7TZauS0N)r   r   r   r   r   r   r   r   r   r   r   rT   rT   rT   rY   r     s   /)F)&r   rc   ZloggingZ	getLoggerr   logZpasslib.utilsr   r   r   r   Zpasslib.utils.binaryr   Zpasslib.utils.compatr   r   r	   r
   Zpasslib.utils.handlersZutilsZhandlersr`   __all__r_   rg   re   rd   rq   r   r   r   ZHasManyBackendsZ	HasRoundsZHasSaltZGenericHandlerrt   r   r   rT   rT   rT   rY   <module>   s2    
	

 B B