U
    ;g,'                     @   s  d dl mZmZmZmZ d dlZddlmZ ddlm	Z	m
Z
mZmZ ddlmZmZmZmZ ddlmZ dd	lmZmZ dd
lmZ dddgZdZddgZdd Zdd Zdd Zde_dd Z z ddl!m"Z" dd Z#dd Z$W n" ek
r   ddl%m$Z$ Y nX dS )    )unicode_literalsdivisionabsolute_importprint_functionN   )pretty_message)buffer_from_bytesbytes_from_buffererrnobyte_string_from_buffer)	type_namestr_clsbyte_cls	int_types)LibraryNotFoundError   )CommonCryptoCommonCryptoConst)Securitypbkdf2
pkcs12_kdf
rand_bytesutf-8cp1252c                 C   sf   zt | tW S  tk
rX   tD ]2}zt | |ddW    Y S  tk
rP   Y q X q Y nX t | ddS )Nstrict)errorsreplace)r   	_encodingUnicodeDecodeError_fallback_encodings)valueencoding r"   6/tmp/pip-unpacked-wheel-x1gypflw/oscrypto/_mac/util.py_try_decode   s    r$   c                  C   sH   t  } zt| }W n tk
r0   t|  Y S X t|tr@|S t|S )z~
    Extracts the last OS error message into a python unicode string

    :return:
        A unicode string error message
    )r
   osstrerror
ValueErrorr   
isinstancer$   )	error_numerror_stringr"   r"   r#   _extract_error*   s    
r+   c                 C   s  t |tsttdt|t |ts8ttdt|t |tsTttdt||dk rdtdt |tsttdt||dk rtd| tdd	d
ddgkrttdt| t	j
t	jt	jt	jt	jd|  }t|}tt	j|t||t|||||	}|dkrtt t|S )a  
    PBKDF2 from PKCS#5

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

    :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

    :raises:
        ValueError - when any of the parameters contain an invalid value
        TypeError - when any of the parameters are of the wrong type
        OSError - when an error is returned by the OS crypto library

    :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   z!iterations must be greater than 0z?
            key_length must be an integer, not %s
            z!key_length must be greater than 0sha1sha224sha256sha384sha512zz
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            )r,   r-   r.   r/   r0   r   )r(   r   	TypeErrorr   r   r   r'   setreprr   ZkCCPRFHmacAlgSHA1ZkCCPRFHmacAlgSHA224ZkCCPRFHmacAlgSHA256ZkCCPRFHmacAlgSHA384ZkCCPRFHmacAlgSHA512r   r   ZCCKeyDerivationPBKDFZ	kCCPBKDF2lenOSErrorr+   r	   )hash_algorithmpasswordsalt
iterations
key_lengthalgooutput_bufferresultr"   r"   r#   r   ?   sh    



	

Fc                 C   sn   t | tsttdt| | dk r,td| dkr<tdt| }ttj	| |}|dkrft
t t|S )a  
    Returns a number of random bytes suitable for cryptographic purposes

    :param length:
        The desired number of bytes

    :raises:
        ValueError - when any of the parameters contain an invalid value
        TypeError - when any of the parameters are of the wrong type
        OSError - when an error is returned by the OS crypto library

    :return:
        A byte string
    z;
            length must be an integer, not %s
            r   zlength must be greater than 0i   z$length must not be greater than 1024r   )r(   r   r1   r   r   r'   r   r   ZSecRandomCopyBytesZkSecRandomDefaultr5   r+   r	   )lengthbufferr=   r"   r"   r#   r      s    

)	libcryptoc                  C   s,   t  } td}t | | t|}t|S )z
        Extracts the last OpenSSL error message into a python unicode string

        :return:
            A unicode string error message
        x   )r@   ERR_get_errorr   ZERR_error_stringr   r$   )r)   r?   r*   r"   r"   r#   _extract_openssl_error   s
    rC   c           
      C   sp  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
dddgkrttdt| |tdddgkrttdt||	d
dd }tjtjtjtjtjtjd|   }t|}t|t||t||||||	}	|	dkrhtt t|S )a  
        KDF from RFC7292 appendix B.2 - https://tools.ietf.org/html/rfc7292#page-19

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

        :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

        :param id_:
            The ID of the usage - 1 for key, 2 for iv, 3 for mac

        :raises:
            ValueError - when any of the parameters contain an invalid value
            TypeError - when any of the parameters are of the wrong type
            OSError - when an error is returned by the OS crypto library

        :return:
            The derived key as a byte string
        zH
                password must be a byte string, not %s
                zD
                salt must be a byte string, not %s
                zG
                iterations must be an integer, not %s
                r   zK
                iterations must be greater than 0 - is %s
                zG
                key_length must be an integer, not %s
                zK
                key_length must be greater than 0 - is %s
                md5r,   r-   r.   r/   r0   z
                hash_algorithm must be one of "md5", "sha1", "sha224", "sha256",
                "sha384", "sha512", not %s
                r      zD
                id_ must be one of 1, 2, 3, not %s
                r   zutf-16bes     )rD   r,   r-   r.   r/   r0   )r(   r   r1   r   r   r   r'   r3   r2   decodeencoder@   ZEVP_md5ZEVP_sha1Z
EVP_sha224Z
EVP_sha256Z
EVP_sha384Z
EVP_sha512r   ZPKCS12_key_gen_unir4   r5   rC   r	   )
r6   r7   r8   r9   r:   Zid_Zutf16_passwordZdigest_typer<   r=   r"   r"   r#   r      s    



	

)r   )&
__future__r   r   r   r   r%   _errorsr   _ffir   r	   r
   r   _typesr   r   r   r   r   r   Z_common_cryptor   r   Z	_securityr   __all__r   r   r$   r+   r   Zpure_pythonr   Z_openssl._libcryptor@   rC   r   Z_pkcs12r"   r"   r"   r#   <module>   s0   e(|