U
    h"                     @   sR   d Z ddlZddlZddlmZ ddlmZ ddlmZ dgZ	G dd de
ZdS )z<passlib.utils.scrypt._builtin -- scrypt() kdf in pure-python    N)izip)pbkdf2_hmac)salsa20ScryptEnginec                   @   sh   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZedd Zdd Zdd	 Zd
d Zdd Zdd ZdS )r   a  
    helper class used to run scrypt kdf, see scrypt() for frontend

    .. warning::
        this class does NO validation of the input ranges or types.

        it's not intended to be used directly,
        but only as a backend for :func:`passlib.utils.scrypt.scrypt()`.
    r   Nc                 C   s   | ||| |||S )z-create engine & run scrypt() hash calculation)run)clssecretsaltnrpkeylen r   D./venv/lib/python3.8/site-packages/passlib/crypto/scrypt/_builtin.pyexecute2   s    zScryptEngine.executec                    s   || _ || _|| _|d> | _| j| | _|d>  | _}|d> | _tddksRt	t
dt| d | _|dkrz| j| _|dkrtd}n.|d	kst	td td
 fdd}|| _d S )N         I<   l    l    ic                    s    | | d> B S )N    r   )XZig1Zig2r   r   
integerifyU   s    z)ScryptEngine.__init__.<locals>.integerify)r
   r   r   
smix_bytesiv_bytesbmix_lenbmix_half_lenstructcalcsizeAssertionErrorStructstrbmix_struct_bmix_1bmixoperator
itemgetterr   )selfr
   r   r   r   r   r   r   r   __init__:   s$    



zScryptEngine.__init__c                    sn   | j }td||d|d | j| jdkr2 }n*| jd fddtd|D }td||d|dS )z
        run scrypt kdf for specified secret, salt, and keylen

        .. note::

            * time cost is ``O(n * r * p)``
            * mem cost is ``O(n * r)``
        Zsha256r   )roundsr       c                 3   s"   | ]} ||  V  qd S Nr   ).0offsetinputsmixr   r   r   	<genexpr>r   s   z#ScryptEngine.run.<locals>.<genexpr>r   )r   r   r3   r   r   joinrange)r*   r   r	   r   r   outputr   r1   r   r   \   s    



zScryptEngine.runc                    s   | j  | j}| j}| jt|| fdd}t| }|j}d }d}|k r||@ }	tdd t||	D }
 |
 |d7 }qR|j	 S )as  run SCrypt smix function on a single input block

        :arg input:
            byte string containing input data.
            interpreted as 32*r little endian 4 byte integers.

        :returns:
            byte string containing output data
            derived by mixing input using n & r parameters.

        .. note:: time & mem cost are both ``O(n * r)``
        c                  3   s2   d} | k r.t }|V   | | d7 } qd S )Nr   r   )tuple)iZlastr'   bufferr
   r   r   vgen   s    
zScryptEngine.smix.<locals>.vgenr   r   c                 s   s   | ]\}}||A V  qd S r.   r   r/   abr   r   r   r4      s     z$ScryptEngine.smix.<locals>.<genexpr>)
r'   r%   r   r
   listunpack__getitem__r8   r   pack)r*   r2   r%   r   r<   VZ
get_v_elemZn_maskr9   jresultr   r:   r   r3   }   s     	


zScryptEngine.smixc                 C   s   | j }|dd }t|}d}||k r|d }tdd t||D  |||< }tdd t||D  ||| || < }|}qdS )a  
        block mixing function used by smix()
        uses salsa20/8 core to mix block contents.

        :arg source:
            source to read from.
            should be list of 32*r 4-byte integers
            (2*r salsa20 blocks).

        :arg target:
            target to write to.
            should be list with same size as source.
            the existing value of this buffer is ignored.

        .. warning::

            this operates *in place* on target,
            so source & target should NOT be same list.

        .. note::

            * time cost is ``O(r)`` -- loops 16*r times, salsa20() has ``O(1)`` cost.

            * memory cost is ``O(1)`` -- salsa20() uses 16 x uint4,
              all other operations done in-place.
        r   Nr      c                 s   s   | ]\}}||A V  qd S r.   r   r=   r   r   r   r4      s     z$ScryptEngine.bmix.<locals>.<genexpr>c                 s   s   | ]\}}||A V  qd S r.   r   r=   r   r   r   r4      s     )r   iterr   r   )r*   sourcetargetZhalftmpZsiterrE   Zjnr   r   r   r'      s    $,zScryptEngine.bmixc                 C   sX   |dd }t dd t|t|D  |dd< }t dd t||D |dd< dS )z0special bmix() method optimized for ``r=1`` caserG   Nc                 s   s   | ]\}}||A V  qd S r.   r   r=   r   r   r   r4      s     z'ScryptEngine._bmix_1.<locals>.<genexpr>c                 s   s   | ]\}}||A V  qd S r.   r   r=   r   r   r   r4      s     )r   r   rH   )r*   rI   rJ   BrK   r   r   r   r&      s    (zScryptEngine._bmix_1)__name__
__module____qualname____doc__r
   r   r   r   r   r   r   r%   r   classmethodr   r+   r   r3   r'   r&   r   r   r   r   r      s"   
"!C()rP   r(   r    Zpasslib.utils.compatr   Zpasslib.crypto.digestr   Zpasslib.crypto.scrypt._salsar   __all__objectr   r   r   r   r   <module>   s   