U
    Law                     @   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)sha1   )sha256    )sha3840   )sha512@   )r   r         c                 C   s   g | ]}t ||fqS  )r   ).0kr   r   9/tmp/pip-unpacked-wheel-8v2dfbvt/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   r8   r   r/   r   r   r   checksum_alg   s    zfshp.checksum_algc                 C   s   | j | j d S )Nr   r9   r:   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 )Nr0   hashr   r   r      )r   checksumr   r   )r   _hash_regexmatchuhexcZInvalidHashErrorgroupr7   r   encoder-   ZMalformedHashError)	r%   r=   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/   rH   r   rG   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)digestsecretr   r   Zkeylen)r1   r   rE   r	   r;   r   r   r<   )r/   rM   r   r   r   _calc_checksum   s    

zfshp._calc_checksum)N)N)&__name__
__module____qualname____doc__nameZsetting_kwdsrB   ZPADDED_BASE64_CHARSZchecksum_charsr   identZdefault_salt_sizeZmax_salt_sizeZdefault_roundsZ
min_roundsZ
max_roundsZrounds_costr$   r8   dictr   r4   classmethodr"   r   r.   r#   propertyr;   r<   recompileXr@   rI   rK   rN   __classcell__r   r   r(   r   r
      sN   )	



	

)rR   base64r   r   rX   logging	getLoggerrO   logZpasslib.utilsr   Zpasslib.utils.handlersutilshandlersrB   Zpasslib.utils.compatr   r   r   r   Zpasslib.crypto.digestr	   __all__Z	HasRoundsZ
HasRawSaltZHasRawChecksumZGenericHandlerr
   r   r   r   r   <module>   s    
