U
    hw                     @   s   d Z ddlmZmZ ddlZddlZeeZddl	m
Z
 ddlm  mZ ddlmZmZmZmZ ddlmZ dgZG dd dejejejejZdS )	zpasslib.handlers.fshp
    )	b64encode	b64decodeN)
to_unicode)bascii_to_str	iteritemsuunicode)pbkdf1fshpc                       s   e Zd ZdZd ZdZejZe	dZ
dZdZdZdZdZd	ZdZd
ddddZedd eD dd eeD  Zed# fdd	ZdZd$ fdd	Zedd Zedd Zedd Zee	dej Z!edd Z"dd  Z#d!d" Z$  Z%S )%r
   ap  This class implements the FSHP 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:

    :param salt:
        Optional raw salt string.
        If not specified, one will be autogenerated (this is recommended).

    :param salt_size:
        Optional number of bytes to use when autogenerating new salts.
        Defaults to 16 bytes, but can be any non-negative value.

    :param rounds:
        Optional number of rounds to use.
        Defaults to 480000, must be between 1 and 4294967295, inclusive.

    :param variant:
        Optionally specifies variant of FSHP to use.

        * ``0`` - uses SHA-1 digest (deprecated).
        * ``1`` - uses SHA-2/256 digest (default).
        * ``2`` - uses SHA-2/384 digest.
        * ``3`` - uses SHA-2/512 digest.

    :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
    )salt	salt_sizeroundsvariantz{FSHP   Ni S    l    Zlinear)Zsha1   )Zsha256    )Zsha3840   )Zsha512@   )r   r         c                 C   s   g | ]}t ||fqS  )r   ).0kr   r   ;./venv/lib/python3.8/site-packages/passlib/handlers/fshp.py
<listcomp>_   s     zfshp.<listcomp>c                 C   s   g | ]\}}|d  |fqS )r   r   )r   r   vr   r   r   r   `   s     c                    s*   t t| jf |}|d k	r&| ||_|S )N)superr
   using_norm_variantdefault_variant)clsr   kwdssubcls	__class__r   r   r   f   s    z
fshp.usingc                    sn   | d| _|d k	r | |}n2| jrJ| j}| ||ksRtd|f ntd|| _tt| j	f | d S )Nuse_defaultszinvalid default variant: %rzno variant specified)
getr&   r   r    AssertionError	TypeErrorr   r   r
   __init__)selfr   r"   r$   r   r   r*   u   s    zfshp.__init__c                 C   sr   t |tr|d}t |trJz| j| }W n tk
rH   tdY nX t |ts\td|| j	krntd|S )Nasciizinvalid fshp variantz'fshp variant must be int or known alias)

isinstancebytesdecoder   _variant_aliasesKeyError
ValueErrorintr)   _variant_info)r!   r   r   r   r   r      s    




zfshp._norm_variantc                 C   s   | j | j d S )Nr   r4   r   r+   r   r   r   checksum_alg   s    zfshp.checksum_algc                 C   s   | j | j d S )Nr   r5   r6   r   r   r   checksum_size   s    zfshp.checksum_sizez
            ^
            \{FSHP
            (\d+)\| # variant
            (\d+)\| # salt size
            (\d+)\} # rounds
            ([a-zA-Z0-9+/]+={0,3}) # digest
            $c           	      C   s   t |dd}| j|}|s(tj| |dddd\}}}}t|}t|}t|}zt|	d}W n  t
k
r   tj| Y nX |d | }||d  }| ||||dS )Nr,   hashr   r   r      )r   checksumr   r   )r   _hash_regexmatchuhexcZInvalidHashErrorgroupr3   r   encoder)   ZMalformedHashError)	r!   r9   mr   r   r   datar   chkr   r   r   from_string   s    zfshp.from_stringc                 C   s4   | j }| j}tt|| }d| jt|| j|f S )Nz{FSHP%d|%d|%d}%s)r;   r   r   r   r   lenr   )r+   rD   r   rC   r   r   r   	to_string   s    zfshp.to_stringc                 C   s.   t |tr|d}t| j| j|| j| jdS )Nzutf-8)Zdigestsecretr   r   Zkeylen)r-   r   rA   r	   r7   r   r   r8   )r+   rH   r   r   r   _calc_checksum   s    

zfshp._calc_checksum)N)N)&__name__
__module____qualname____doc__nameZsetting_kwdsr>   ZPADDED_BASE64_CHARSZchecksum_charsr   identZdefault_salt_sizeZmax_salt_sizeZdefault_roundsZ
min_roundsZ
max_roundsZrounds_costr    r4   dictr   r0   classmethodr   r   r*   r   propertyr7   r8   recompileXr<   rE   rG   rI   __classcell__r   r   r$   r   r
      sN   )	



	

)rM   base64r   r   rS   ZloggingZ	getLoggerrJ   logZpasslib.utilsr   Zpasslib.utils.handlersZutilsZhandlersr>   Zpasslib.utils.compatr   r   r   r   Zpasslib.crypto.digestr	   __all__Z	HasRoundsZ
HasRawSaltZHasRawChecksumZGenericHandlerr
   r   r   r   r   <module>   s    
