def _verify(certificate_or_public_key, signature, data, hash_algorithm):
if not isinstance(certificate_or_public_key, (Certificate, PublicKey)):<EOL><INDENT>raise TypeError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>type_name(certificate_or_public_key)<EOL>))<EOL><DEDENT>if not isinstance(signature, byte_cls):<EOL><INDENT>raise TypeError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>type_name(signature)<EOL>))<EOL><DEDENT>if not isinstance(data, byte_cls):<EOL><INDENT>raise TypeError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>type_name(data)<EOL>))<EOL><DEDENT>valid_hash_algorithms = set(['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'])<EOL>if certificate_or_public_key.algorithm == '<STR_LIT>':<EOL><INDENT>valid_hash_algorithms |= set(['<STR_LIT>'])<EOL><DEDENT>if hash_algorithm not in valid_hash_algorithms:<EOL><INDENT>valid_hash_algorithms_error = '<STR_LIT>'<EOL>if certificate_or_public_key.algorithm == '<STR_LIT>':<EOL><INDENT>valid_hash_algorithms_error += '<STR_LIT>'<EOL><DEDENT>raise ValueError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>valid_hash_algorithms_error,<EOL>repr(hash_algorithm)<EOL>))<EOL><DEDENT>if certificate_or_public_key.algorithm == '<STR_LIT>' and hash_algorithm == '<STR_LIT>':<EOL><INDENT>if len(data) > certificate_or_public_key.byte_size - <NUM_LIT:11>:<EOL><INDENT>raise ValueError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>certificate_or_public_key.byte_size,<EOL>len(data)<EOL>))<EOL><DEDENT>result = Security.SecKeyRawVerify(<EOL>certificate_or_public_key.sec_key_ref,<EOL>SecurityConst.kSecPaddingPKCS1,<EOL>data,<EOL>len(data),<EOL>signature,<EOL>len(signature)<EOL>)<EOL>if result == SecurityConst.errSecVerifyFailed or result == SecurityConst.errSSLCrypto:<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT>handle_sec_error(result)<EOL>return<EOL><DEDENT>cf_signature = None<EOL>cf_data = None<EOL>cf_hash_length = None<EOL>sec_transform = None<EOL>try:<EOL><INDENT>error_pointer = new(CoreFoundation, '<STR_LIT>')<EOL>cf_signature = CFHelpers.cf_data_from_bytes(signature)<EOL>sec_transform = Security.SecVerifyTransformCreate(<EOL>certificate_or_public_key.sec_key_ref,<EOL>cf_signature,<EOL>error_pointer<EOL>)<EOL>handle_cf_error(error_pointer)<EOL>hash_constant = {<EOL>'<STR_LIT>': Security.kSecDigestMD5,<EOL>'<STR_LIT>': Security.kSecDigestSHA1,<EOL>'<STR_LIT>': Security.kSecDigestSHA2,<EOL>'<STR_LIT>': Security.kSecDigestSHA2,<EOL>'<STR_LIT>': Security.kSecDigestSHA2,<EOL>'<STR_LIT>': Security.kSecDigestSHA2<EOL>}[hash_algorithm]<EOL>Security.SecTransformSetAttribute(<EOL>sec_transform,<EOL>Security.kSecDigestTypeAttribute,<EOL>hash_constant,<EOL>error_pointer<EOL>)<EOL>handle_cf_error(error_pointer)<EOL>if hash_algorithm in set(['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>hash_length = {<EOL>'<STR_LIT>': <NUM_LIT>,<EOL>'<STR_LIT>': <NUM_LIT>,<EOL>'<STR_LIT>': <NUM_LIT>,<EOL>'<STR_LIT>': <NUM_LIT><EOL>}[hash_algorithm]<EOL>cf_hash_length = CFHelpers.cf_number_from_integer(hash_length)<EOL>Security.SecTransformSetAttribute(<EOL>sec_transform,<EOL>Security.kSecDigestLengthAttribute,<EOL>cf_hash_length,<EOL>error_pointer<EOL>)<EOL>handle_cf_error(error_pointer)<EOL><DEDENT>if certificate_or_public_key.algorithm == '<STR_LIT>':<EOL><INDENT>Security.SecTransformSetAttribute(<EOL>sec_transform,<EOL>Security.kSecPaddingKey,<EOL>Security.kSecPaddingPKCS1Key,<EOL>error_pointer<EOL>)<EOL>handle_cf_error(error_pointer)<EOL><DEDENT>cf_data = CFHelpers.cf_data_from_bytes(data)<EOL>Security.SecTransformSetAttribute(<EOL>sec_transform,<EOL>Security.kSecTransformInputAttributeName,<EOL>cf_data,<EOL>error_pointer<EOL>)<EOL>handle_cf_error(error_pointer)<EOL>res = Security.SecTransformExecute(sec_transform, error_pointer)<EOL>if not is_null(error_pointer):<EOL><INDENT>error = unwrap(error_pointer)<EOL>if not is_null(error):<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT><DEDENT>res = bool(CoreFoundation.CFBooleanGetValue(res))<EOL>if not res:<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT><DEDENT>finally:<EOL><INDENT>if sec_transform:<EOL><INDENT>CoreFoundation.CFRelease(sec_transform)<EOL><DEDENT>if cf_signature:<EOL><INDENT>CoreFoundation.CFRelease(cf_signature)<EOL><DEDENT>if cf_data:<EOL><INDENT>CoreFoundation.CFRelease(cf_data)<EOL><DEDENT>if cf_hash_length:<EOL><INDENT>CoreFoundation.CFRelease(cf_hash_length)<EOL><DEDENT><DEDENT>
Verifies an RSA, DSA or ECDSA signature

:param certificate_or_public_key:
    A Certificate or PublicKey instance to verify the signature with

:param signature:
    A byte string of the signature to verify

:param data:
    A byte string of the data the signature is for

:param hash_algorithm:
    A unicode string of "md5", "sha1", "sha224", "sha256", "sha384" or "sha512"

:raises:
    oscrypto.errors.SignatureError - when the signature is determined to be invalid
    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