def pbkdf2(hash_algorithm, password, salt, iterations, key_length):

    if not isinstance(password, byte_cls):
        raise TypeError(pretty_message(
            '''
            password must be a byte string, not %s
            ''',
            type_name(password)
        ))

    if not isinstance(salt, byte_cls):
        raise TypeError(pretty_message(
            '''
            salt must be a byte string, not %s
            ''',
            type_name(salt)
        ))

    if not isinstance(iterations, int_types):
        raise TypeError(pretty_message(
            '''
            iterations must be an integer, not %s
            ''',
            type_name(iterations)
        ))

    if iterations < 1:
        raise ValueError('iterations must be greater than 0')

    if not isinstance(key_length, int_types):
        raise TypeError(pretty_message(
            '''
            key_length must be an integer, not %s
            ''',
            type_name(key_length)
        ))

    if key_length < 1:
        raise ValueError('key_length must be greater than 0')

    if hash_algorithm not in set(['sha1', 'sha256', 'sha384', 'sha512']):
        raise ValueError(pretty_message(
            '''
            hash_algorithm must be one of "sha1", "sha256", "sha384", "sha512",
            not %s
            ''',
            repr(hash_algorithm)
        ))

    alg_constant = {
        'sha1': BcryptConst.BCRYPT_SHA1_ALGORITHM,
        'sha256': BcryptConst.BCRYPT_SHA256_ALGORITHM,
        'sha384': BcryptConst.BCRYPT_SHA384_ALGORITHM,
        'sha512': BcryptConst.BCRYPT_SHA512_ALGORITHM
    }[hash_algorithm]

    alg_handle = None

    try:
        alg_handle = open_alg_handle(alg_constant, BcryptConst.BCRYPT_ALG_HANDLE_HMAC_FLAG)

        output_buffer = buffer_from_bytes(key_length)
        res = bcrypt.BCryptDeriveKeyPBKDF2(
            alg_handle,
            password,
            len(password),
            salt,
            len(salt),
            iterations,
            output_buffer,
            key_length,
            0
        )
        handle_error(res)

        return bytes_from_buffer(output_buffer)
    finally:
        if alg_handle:
            close_alg_handle(alg_handle)
PBKDF2 from PKCS#5
dataset/ETHPy150Open wbond/oscrypto/oscrypto/_win/util.py/pbkdf2