U
    h%                     @   s   d Z ddlmZ ddlZeeZddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	gZd
ZdZdZdd ZdZd"ddZdadad#dd	Zdd Zdd Zdd ZdZeeeedZd$ddZed d d! Z dS )%zg
passlib.utils.scrypt -- scrypt hash frontend and help utilities

XXX: add this module to public docs?
    )absolute_importN)warn)exc)to_bytes)PYPYvalidatescryptl    i?c                 C   sh   |dk rt d| |dk r(t d| || tkrDt d||f | dk sX| | d @ rdt d|  dS )aI  
    helper which validates a set of scrypt config parameters.
    scrypt will take ``O(n * r * p)`` time and ``O(n * r)`` memory.
    limitations are that ``n = 2**<positive integer>``, ``n < 2**(16*r)``, ``r * p < 2 ** 30``.

    :param n: scrypt rounds
    :param r: scrypt block size
    :param p: scrypt parallel factor
       zr must be > 0: r=%rzp must be > 0: p=%rz!r * p must be < 2**30: r=%r, p=%r   z%n must be > 1, and a power of 2: n=%rT)
ValueErrorMAX_RP)nrp r   D./venv/lib/python3.8/site-packages/passlib/crypto/scrypt/__init__.pyr   )   s    
   ?c                 C   s,   |d| d| d  t    }t|| }|S )a?  
    calculate memory required for parameter combination.
    assumes parameters have already been validated.

    .. warning::
        this is derived from OpenSSL's scrypt maxmem formula;
        and may not be correct for other implementations
        (additional buffers, different parallelism tradeoffs, etc).
           r   )UINT32_SIZEint)r   r   r   Zfudgemaxmemr   r   r   estimate_maxmemH   s    r   r
   r   c                 C   sZ   t ||| t| dd} t|dd}|dk r4td|tkrHtdt t| |||||S )a4  run SCrypt key derivation function using specified parameters.

    :arg secret:
        passphrase string (unicode is encoded to bytes using utf-8).

    :arg salt:
        salt string (unicode is encoded to bytes using utf-8).

    :arg n:
        integer 'N' parameter

    :arg r:
        integer 'r' parameter

    :arg p:
        integer 'p' parameter

    :arg keylen:
        number of bytes of key to generate.
        defaults to 32 (the internal block size).

    :returns:
        a *keylen*-sized bytes instance

    SCrypt imposes a number of constraints on it's input parameters:

    * ``r * p < 2**30`` -- due to a limitation of PBKDF2-HMAC-SHA256.
    * ``keylen < (2**32 - 1) * 32`` -- due to a limitation of PBKDF2-HMAC-SHA256.
    * ``n`` must a be a power of 2, and > 1 -- internal limitation of scrypt() implementation

    :raises ValueError: if the provided parameters are invalid (see constraints above).

    .. warning::

        Unless the third-party ``scrypt <https://pypi.python.org/pypi/scrypt/>``_ package
        is installed, passlib will use a builtin pure-python implementation of scrypt,
        which is *considerably* slower (and thus requires a much lower / less secure
        ``n`` value in order to be usuable). Installing the :mod:`!scrypt` package
        is strongly recommended.
    secret)Zparamsaltr
   zkeylen must be at least 1zkeylen too large, must be <= %d)r   r   r   
MAX_KEYLEN_scrypt)r   r   r   r   r   keylenr   r   r   r   k   s    )c                  C   s.   t rdnd} td|  tj ddlm} |jS )zD
    Load pure-python scrypt implementation built into passlib.
    
   d   zUsing builtin scrypt backend, which is %dx slower than is required for adequate security. Installing scrypt support (via 'pip install scrypt') is strongly recommendedr
   )ScryptEngine)r   r   r   ZPasslibSecurityWarningZ_builtinr"   Zexecute)Zslowdownr"   r   r   r   _load_builtin_backend   s    r#   c               
   C   s   zddl m}  | W S  tk
r&   Y nX zddl }W n: tk
rn } zdt|kr^tdtj W 5 d}~X Y nX tdtj dS )z
    Try to import the ctypes-based scrypt hash function provided by the
    ``scrypt <https://pypi.python.org/pypi/scrypt/>``_ package.
    r   )hashNr   zJ'scrypt' package failed to import correctly (possible installation issue?)z5'scrypt' package is too old (lacks ``hash()`` method))r   r$   ImportErrorstrr   r   ZPasslibWarning)r$   r   errr   r   r   _load_cffi_backend   s    r(   c                     s8   zddl m  W n tk
r&   Y dS X  fdd} | S )zf
    Attempt to load stdlib scrypt() implement and return wrapper.
    Returns None if not found.
    r   )r   Nc              	      s.   t }|dk rt|||} | ||||||dS )Nr   )Zpasswordr   r   r   r   Zdklenr   )SCRYPT_MAXMEMr   )r   r   r   r   r   r   r   Zstdlib_scryptr   r   stdlib_scrypt_wrapper   s    z3_load_stdlib_backend.<locals>.stdlib_scrypt_wrapper)Zhashlibr   r%   )r+   r   r*   r   _load_stdlib_backend   s    r,   )Zstdlibr   ZbuiltinFc              	   C   s   | dkrdS | dkrXt D ]2} zt| |dW   S  tjk
rH   Y qY qX qtdnDt| }|sttd| f | }|std|  |rdS | a|adS )z
    set backend for scrypt(). if name not specified, loads first available.

    :raises ~passlib.exc.MissingBackendError: if backend can't be found

    .. note:: mainly intended to be called by unittests, and scrypt hash handler
    anyNdefaultdryrunzno scrypt backends availablezunknown scrypt backend: %rzscrypt backend %r not available)	backend_values_set_backendr   MissingBackendError_backend_loadersgetr   backendr   )namer0   loaderr$   r   r   r   r2      s&    
r2   r.   c                 C   s0   zt | dd W dS  tjk
r*   Y dS X d S )NTr/   F)r2   r   r3   )r7   r   r   r   _has_backend  s
    r9   )r   )r
   r   )F)!__doc__Z
__future__r   ZloggingZ	getLogger__name__logwarningsr   Zpasslibr   Zpasslib.utilsr   Zpasslib.utils.compatr   __all__r)   r   r   r   r   r   r   r6   r   r#   r(   r,   r1   dictr4   r2   r9   r   r   r   r   <module>   s>    


3!
