#NEWLINE# def pbkdf2( hash_algorithm , password , salt , iterations , key_length ) : #NEWLINE# #INDENT# '\n    PBKDF2 from PKCS#5\n\n    :param hash_algorithm:\n        The string name of the hash algorithm to use: "sha1", "sha256", "sha384", "sha512"\n\n    :param password:\n        A byte string of the password to use an input to the KDF\n\n    :param salt:\n        A cryptographic random byte string\n\n    :param iterations:\n        The numbers of iterations to use when deriving the key\n\n    :param key_length:\n        The length of the desired key in bytes\n\n    :raises:\n        ValueError - when any of the parameters contain an invalid value\n        TypeError - when any of the parameters are of the wrong type\n        OSError - when an error is returned by the OS crypto library\n\n    :return:\n        The derived key as a byte string\n    ' #NEWLINE# if ( not isinstance ( password , byte_cls ) ) : #NEWLINE# #INDENT# raise TypeError ( pretty_message ( '\n            password must be a byte string, not %s\n            ' , type_name ( password ) ) ) #NEWLINE# #UNINDENT# if ( not isinstance ( salt , byte_cls ) ) : #NEWLINE# #INDENT# raise TypeError ( pretty_message ( '\n            salt must be a byte string, not %s\n            ' , type_name ( salt ) ) ) #NEWLINE# #UNINDENT# if ( not isinstance ( iterations , int_types ) ) : #NEWLINE# #INDENT# raise TypeError ( pretty_message ( '\n            iterations must be an integer, not %s\n            ' , type_name ( iterations ) ) ) #NEWLINE# #UNINDENT# if ( iterations < 1 ) : #NEWLINE# #INDENT# raise ValueError ( 'iterations must be greater than 0' ) #NEWLINE# #UNINDENT# if ( not isinstance ( key_length , int_types ) ) : #NEWLINE# #INDENT# raise TypeError ( pretty_message ( '\n            key_length must be an integer, not %s\n            ' , type_name ( key_length ) ) ) #NEWLINE# #UNINDENT# if ( key_length < 1 ) : #NEWLINE# #INDENT# raise ValueError ( 'key_length must be greater than 0' ) #NEWLINE# #UNINDENT# if ( hash_algorithm not in set ( [ 'sha1' , 'sha256' , 'sha384' , 'sha512' ] ) ) : #NEWLINE# #INDENT# raise ValueError ( pretty_message ( '\n            hash_algorithm must be one of "sha1", "sha256", "sha384", "sha512",\n            not %s\n            ' , repr ( hash_algorithm ) ) ) #NEWLINE# #UNINDENT# alg_constant = { #NEWLINE# #INDENT# 'sha1' : BcryptConst . BCRYPT_SHA1_ALGORITHM , #NEWLINE# 'sha256' : BcryptConst . BCRYPT_SHA256_ALGORITHM , #NEWLINE# 'sha384' : BcryptConst . BCRYPT_SHA384_ALGORITHM , #NEWLINE# 'sha512' : BcryptConst . BCRYPT_SHA512_ALGORITHM , #NEWLINE# #UNINDENT# } [ hash_algorithm ] #NEWLINE# alg_handle = None #NEWLINE# try : #NEWLINE# #INDENT# alg_handle = open_alg_handle ( alg_constant , BcryptConst . BCRYPT_ALG_HANDLE_HMAC_FLAG ) #NEWLINE# output_buffer = buffer_from_bytes ( key_length ) #NEWLINE# res = bcrypt . BCryptDeriveKeyPBKDF2 ( alg_handle , password , len ( password ) , salt , len ( salt ) , iterations , output_buffer , key_length , 0 ) #NEWLINE# handle_error ( res ) #NEWLINE# return bytes_from_buffer ( output_buffer ) #NEWLINE# #UNINDENT# finally : #NEWLINE# #INDENT# if alg_handle : #NEWLINE# #INDENT# close_alg_handle ( alg_handle )