U
    ;g                     @   s.  d dl mZmZmZm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dlmZmZmZ ddlmZ dd	lmZmZ e	 Zed
krddlmZmZ nBedksedkrddlmZmZ ddlmZmZ nddlmZmZ ddddgZejdkrdd Z dd Z!ndd Z dd Z!dddZ"dd Z#dS )    )unicode_literalsdivisionabsolute_importprint_functionN)datetime   )backend)
rand_bytes)	type_namebyte_cls	int_types)pretty_message)newderefmac)pbkdf2
pkcs12_kdfwinZ	winlegacy)kernel32handle_errorpbkdf1r   pbkdf2_iteration_calculatorr   win32c                  C   s$   t td} t| }t| t| S )NzLARGE_INTEGER *)r   r   ZQueryPerformanceCounterr   r   )numberres r   0/tmp/pip-unpacked-wheel-x1gypflw/oscrypto/kdf.py
_get_start$   s    

r   c                 C   s   t  |  }t|d S )Ng     @@)r   int)startlengthr   r   r   _get_elapsed*   s    
r!   c                   C   s   t  S )N)r   nowr   r   r   r   r   /   s    c                 C   s:   t  |  }|j|jd d  }|jd }t||d  S )N   i  i  )r   r"   secondsdaysmicrosecondsr   )r   r    r$   Zmillisecondsr   r   r   r!   2   s    
d   Fc                    s2   t dddddgkr(ttdt ttsDttdtdk r^ttd	tttszttd
tdk rttdttj	rt
tddddt fdd}| }t| d | }| dk rdnd}tt|}|dkr.|d d }|S )a  
    Runs pbkdf2() twice to determine the approximate number of iterations to
    use to hit a desired time per run. Use this on a production machine to
    dynamically adjust the number of iterations as high as you can.

    :param hash_algorithm:
        The string name of the hash algorithm to use: "md5", "sha1", "sha224",
        "sha256", "sha384", "sha512"

    :param key_length:
        The length of the desired key in bytes

    :param target_ms:
        The number of milliseconds the derivation should take

    :param quiet:
        If no output should be printed as attempts are made

    :return:
        An integer number of iterations of PBKDF2 using the specified hash
        that will take at least target_ms
    sha1sha224sha256sha384sha512zz
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            ?
            key_length must be an integer, not %s
            r   C
            key_length must be greater than 0 - is %s
            z>
            target_ms must be an integer, not %s
            zB
            target_ms must be greater than 0 - is %s
            z
            Only a very slow, pure-python version of PBKDF2 is available,
            making this function useless
            i'  zthis is a testzutf-8c                     s>   t  } t  t| }s2td|f  d | S )Nz%s iterations in %smsg      ?)r   r   r!   print)r   Zobserved_mshash_algorithm
iterations
key_lengthpasswordquietsalt	target_msr   r   _measure   s    z-pbkdf2_iteration_calculator.<locals>._measureg       @i i N  i  )set
ValueErrorr   repr
isinstancer   	TypeErrorr
   r   Zpure_pythonOSErrorencoder	   r   round)r1   r3   r7   r5   r8   fractionZround_factorresultr   r0   r   r   9   sT    




c                 C   sd  t |tsttdt|t |ts8ttdt|t |tsTttdt||dk rnttdt|t |tsttdt||dk rttdt|| tdd	d
gkrttdt| |dkr| tdd	gkrttd| t|f|dkr| d
krttdt|t	t
| }|||  }td|d D ]}|| }qD|d| S )aF  
    An implementation of PBKDF1 - should only be used for interop with legacy
    systems, not new architectures

    :param hash_algorithm:
        The string name of the hash algorithm to use: "md2", "md5", "sha1"

    :param password:
        A byte string of the password to use an input to the KDF

    :param salt:
        A cryptographic random byte string

    :param iterations:
        The numbers of iterations to use when deriving the key

    :param key_length:
        The length of the desired key in bytes

    :return:
        The derived key as a byte string
    z@
            password must be a byte string, not %s
            z<
            salt must be a byte string, not %s
            z?
            iterations must be an integer, not %s
            r   zC
            iterations must be greater than 0 - is %s
            r-   r.   Zmd2md5r(   zT
            hash_algorithm must be one of "md2", "md5", "sha1", not %s
               zM
            key_length can not be longer than 16 for %s - is %s
               zO
            key_length can not be longer than 20 for sha1 - is %s
               N)r>   r   r?   r   r
   r   r<   r=   r;   getattrhashlibdigestrange)r1   r4   r6   r2   r3   algooutput_r   r   r   r      sd    





)r'   F)$
__future__r   r   r   r   sysrJ   r    r   utilr	   _typesr
   r   r   _errorsr   _ffir   r   Z_backendZ	_mac.utilr   r   Z	_win.utilZ_win._kernel32r   r   Z_openssl.util__all__platformr   r!   r   r   r   r   r   r   <module>   s6   

g