B
    hAZ#                 @   s0  d Z ddlZddlZddl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 ddlmZmZmZmZmZmZmZ dZd	Zed
jZeeddZe	 Zedd ejjejj gD Z!dd Z"e" Z#eddfddZ$e%edZ&eddfddZ'dd Z(dd Z)dd Z*d#ddZ+dd  Z,d!d" Z-dS )$z
    werkzeug.security
    ~~~~~~~~~~~~~~~~~

    Security related helpers such as secure password hashing tools.

    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
    N)Struct)SystemRandom)xor)starmap)
range_typePY2	text_typeizipto_bytesstring_types	to_nativeZ>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789iP  z>IZcompare_digestc             c   s   | ]}|d kr|V  qdS ))N/N ).0sepr   r   0lib/python3.7/site-packages/werkzeug/security.py	<genexpr>    s    r   c              C   sJ   t tdd } | d krd} i }x(| D ] }t t|d }|d k	r"|||< q"W |S )NZ
algorithms)Zmd5Zsha1Zsha224sha256Zsha384Zsha512)getattrhashlib)ZalgosrvZalgofuncr   r   r   _find_hashlib_algorithms$   s    
r   c             C   s    t | ||||}tt|dS )a)  Like :func:`pbkdf2_bin`, but returns a hex-encoded string.

    .. versionadded:: 0.9

    :param data: the data to derive.
    :param salt: the salt for the derivation.
    :param iterations: the number of iterations.
    :param keylen: the length of the resulting key.  If not provided,
                   the digest size will be used.
    :param hashfunc: the hash function to use.  This can either be the
                     string name of a known hash function, or a function
                     from the hashlib module.  Defaults to sha256.
    	hex_codec)
pbkdf2_binr   codecsencode)datasalt
iterationskeylenhashfuncr   r   r   r   
pbkdf2_hex1   s    r"   pbkdf2_hmacc             C   s  t |trt| }n
|stj}t| } t|}tr`| }t|dr`|jtkr`t	|j| |||S t
| d|}|sx|j}|fdd}t }xttd| |j  d D ]X}	||t|	  }
}x4t|d D ]$}|t|}tttt|
|}
qW ||
 qW t|d| S )a  Returns a binary digest for the PBKDF2 hash algorithm of `data`
    with the given `salt`. It iterates `iterations` times and produces a
    key of `keylen` bytes. By default, SHA-256 is used as hash function;
    a different hashlib `hashfunc` can be provided.

    .. versionadded:: 0.9

    :param data: the data to derive.
    :param salt: the salt for the derivation.
    :param iterations: the number of iterations.
    :param keylen: the length of the resulting key.  If not provided
                   the digest size will be used.
    :param hashfunc: the hash function to use.  This can either be the
                     string name of a known hash function or a function
                     from the hashlib module.  Defaults to sha256.
    nameNc             S   s   |  }||  t| S )N)copyupdate	bytearrayZdigest)xmachr   r   r   _pseudorandomn   s    
z!pbkdf2_bin.<locals>._pseudorandom   )
isinstancer   _hash_funcsr   r   r
   _has_native_pbkdf2hasattrr$   r#   hmacHMACZdigest_sizer'   r   	_pack_intbytesr   r   r	   extend)r   r   r   r    r!   Z
_test_hashr)   r+   Zbufblockr   uir   r   r   r   G   s2    



r   c             C   s   t | tr| d} t |tr(|d}tdk	r:t| |S t| t|krNdS d}trxPt| |D ]\}}|t|t|A O }qbW n$x"t| |D ]\}}|||A O }qW |dkS )zThis function compares strings in somewhat constant time.  This
    requires that the length of at least one string is known in advance.

    Returns `True` if the two strings are equal, or `False` if they are not.

    .. versionadded:: 0.7
    zutf-8NFr   )r-   r   r   _builtin_safe_str_cmplenr   r	   ord)abr   r(   yr   r   r   safe_str_cmp|   s    




r?   c             C   s(   | dkrt dddd t| D S )zAGenerate a random string of SALT_CHARS with specified ``length``.r   zSalt length must be positive c             s   s   | ]}t tV  qd S )N)_sys_rngZchoice
SALT_CHARS)r   _r   r   r   r      s    zgen_salt.<locals>.<genexpr>)
ValueErrorjoinr   )lengthr   r   r   gen_salt   s    rG   c       
      C   s  | dkr|| fS t |tr$|d}| dr| dd d}t|dkrTtd|d	} |rrt|d	 pnd	ptt	}d
}d| |f }nd}| }t
| }|dkrtd|  |r|stdt||||d}nD|rt |tr|d}t||| }n| }	|	| |	 }||fS )zInternal password hash helper.  Supports plaintext without salt,
    unsalted and salted passwords.  In case salted passwords are used
    hmac is used.
    plainzutf-8zpbkdf2:   N:)r,      z&Invalid number of arguments for PBKDF2r   Tzpbkdf2:%s:%dFzinvalid method %rzSalt is required for PBKDF2)r!   )r-   r   r   
startswithsplitr:   rD   popintDEFAULT_PBKDF2_ITERATIONSr.   get	TypeErrorr"   r1   r2   Z	hexdigestr&   )
methodr   passwordargsr   Z	is_pbkdf2actual_methodZ	hash_funcr   r*   r   r   r   _hash_internal   s<    








rW   pbkdf2:sha256   c             C   s2   |dkrt |pd}t||| \}}d|||f S )a  Hash a password with the given method and salt with a string of
    the given length. The format of the string returned includes the method
    that was used so that :func:`check_password_hash` can check the hash.

    The format for the hashed string looks like this::

        method$salt$hash

    This method can **not** generate unsalted passwords but it is possible
    to set param method='plain' in order to enforce plaintext passwords.
    If a salt is used, hmac is used internally to salt the password.

    If PBKDF2 is wanted it can be enabled by setting the method to
    ``pbkdf2:method:iterations`` where iterations is optional::

        pbkdf2:sha256:80000$salt$hash
        pbkdf2:sha256$salt$hash

    :param password: the password to hash.
    :param method: the hash method to use (one that hashlib supports). Can
                   optionally be in the format ``pbkdf2:<method>[:iterations]``
                   to enable PBKDF2.
    :param salt_length: the length of the salt in letters.
    rH   r@   z%s$%s$%s)rG   rW   )rT   rS   Zsalt_lengthr   r*   rV   r   r   r   generate_password_hash   s    rZ   c             C   s:   |  ddk rdS | dd\}}}tt|||d |S )a  check a password against a given salted and hashed password value.
    In order to support unsalted legacy passwords this method supports
    plain text passwords, md5 and sha1 hashes (both salted and unsalted).

    Returns `True` if the password matched, `False` otherwise.

    :param pwhash: a hashed string like returned by
                   :func:`generate_password_hash`.
    :param password: the plaintext password to compare against the hash.
    $rK   Fr   )countrM   r?   rW   )ZpwhashrT   rS   r   Zhashvalr   r   r   check_password_hash   s    r]   c             G   sv   | g}xd|D ]\}|dkr"t |}xtD ]}||kr(dS q(W tj|sZ|dksZ|dr^dS || qW t j| S )zSafely join `directory` and one or more untrusted `pathnames`.  If this
    cannot be done, this function returns ``None``.

    :param directory: the base directory.
    :param pathnames: the untrusted pathnames relative to that directory.
    r@   Nz..z../)		posixpathnormpath_os_alt_sepsospathisabsrL   appendrE   )Z	directoryZ	pathnamespartsfilenamer   r   r   r   	safe_join   s    



rg   )rX   rY   ).__doc__ra   r1   r   r^   r   Zstructr   Zrandomr   operatorr   	itertoolsr   Zwerkzeug._compatr   r   r   r	   r
   r   r   rB   rP   Zpackr3   r   r9   rA   listrb   r   altsepr`   r   r.   r"   r0   r/   r   r?   rG   rW   rZ   r]   rg   r   r   r   r   <module>
   s:   $


4+
