U
    øÐLa(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 s˜tdƒ‚|r¨t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sˆt‚||dt|d ƒ  ƒ ¡ d|… }t|ƒ|ksÂt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   ú?/tmp/pip-unpacked-wheel-8v2dfbvt/passlib/handlers/sha2_crypt.pyÚ
<listcomp>Û   s     z#_raw_sha2_crypt.<locals>.<listcomp>r0   )Ú
isinstancer
   ÚencodeÚbytesÚAssertionErrorÚ_BNULLÚuhÚexcZNullPasswordErrorr   r   ÚlenÚhashlibÚsha512Ú_512_transpose_mapÚsha256Ú_256_transpose_mapÚdigestÚupdater   r   Ú_c_digest_offsetsÚdivmodr   Zencode_transposed_bytesÚdecode)ÚpwdÚsaltÚroundsZuse_512Zpwd_lenZsalt_lenZ
hash_constZtranspose_mapÚdbZa_ctxZa_ctx_updateÚiÚdaZdpZtmp_ctxZtmp_ctx_updateZdsZdp_dpZdp_dsÚdataÚdcÚblocksÚtailrV   rW   ÚpairsrT   rX   rY   Ú_raw_sha2_crypt8   sl    !




$.  
rx   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)rn   ro   Úimplicit_roundsZ	salt_sizer#   rP   rQ   ZlinearFNc                    s4   t t| ƒjf |Ž |d kr*| jo(| jdk}|| _d S )Néˆ  )Úsuperr{   Ú__init__Zuse_defaultsro   r|   )Úselfr|   Úkwds©Ú	__class__rT   rY   r     s    z_SHA2_Common.__init__c                 C   s   | j || jd kdS ©N)Zrelaxed)Z
_norm_saltÚchecksum)r€   rn   rT   rT   rY   Ú_parse_salt  s    z_SHA2_Common._parse_saltc                 C   s   | j || jd kdS r„   )Z_norm_roundsr…   )r€   ro   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
¡r¦tt
ƒdksht‚| d¡dd … }| t¡r˜|tkr˜tj | ¡‚t|ƒ}d}nd}d}t|ƒd	krÄ|\}}n&t|ƒd
krÞ|d }d }ntj | ¡‚| |||pöd |dS )NrR   Úhashr   r   r&   Fr}   Tr   r   )ro   rn   r…   r|   )r   ÚidentÚ
startswithr`   ra   ZInvalidHashErrorrb   r^   ÚsplitÚ_UDOLLARÚ_UROUNDSÚpopÚ_UZEROZZeroPaddedRoundsErrorÚintZMalformedHashError)Úclsrˆ   r‰   Úpartsro   r|   rn   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 )Nr}   z%s%s$%sÚ z%srounds=%d$%s$%s)ro   r|   r   r‰   rn   r…   r	   )r€   rˆ   rT   rT   rY   Ú	to_stringT  s    ÿ ÿz_SHA2_Common.to_string)Zos_cryptÚ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)r€   ÚsecretÚ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)rx   rn   ro   Ú_cdb_use_512)r€   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_prefixr|   r   r†   r‡   Úclassmethodr“   r•   Úbackendsr—   r›   r™   r¡   rœ   Ú__classcell__rT   rT   r‚   rY   r{   ý   s2   
,

r{   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   ÚloggingÚ	getLoggerr£   ÚlogZpasslib.utilsr   r   r   r   Zpasslib.utils.binaryr   Zpasslib.utils.compatr   r   r	   r
   Zpasslib.utils.handlersÚutilsÚhandlersr`   Ú__all__r_   rj   rg   re   rx   r   rŒ   r   ZHasManyBackendsZ	HasRoundsZHasSaltZGenericHandlerr{   r   r   rT   rT   rT   rY   Ú<module>   s2    
þ	

 Bÿ B