def ecdsa_verify(certificate_or_public_key, signature, data, hash_algorithm):
has_asn1 = hasattr(certificate_or_public_key, '<STR_LIT>')<EOL>if not has_asn1 or not isinstance(certificate_or_public_key.asn1, (keys.PublicKeyInfo, Certificate)):<EOL><INDENT>raise TypeError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>type_name(certificate_or_public_key)<EOL>))<EOL><DEDENT>curve_name = certificate_or_public_key.curve<EOL>if curve_name not in set(['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>raise ValueError(pretty_message(<EOL>'''<STR_LIT>'''<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>if hash_algorithm not in set(['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>raise ValueError(pretty_message(<EOL>'''<STR_LIT>''',<EOL>repr(hash_algorithm)<EOL>))<EOL><DEDENT>asn1 = certificate_or_public_key.asn1<EOL>if isinstance(asn1, Certificate):<EOL><INDENT>asn1 = asn1.public_key<EOL><DEDENT>curve_base_point = {<EOL>'<STR_LIT>': SECP256R1_BASE_POINT,<EOL>'<STR_LIT>': SECP384R1_BASE_POINT,<EOL>'<STR_LIT>': SECP521R1_BASE_POINT,<EOL>}[curve_name]<EOL>x, y = asn1['<STR_LIT>'].to_coords()<EOL>n = curve_base_point.order<EOL>public_key_point = PrimePoint(curve_base_point.curve, x, y, n)<EOL>try:<EOL><INDENT>signature = DSASignature.load(signature)<EOL>r = signature['<STR_LIT:r>'].native<EOL>s = signature['<STR_LIT:s>'].native<EOL><DEDENT>except (ValueError):<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT>invalid = <NUM_LIT:0><EOL>invalid |= r < <NUM_LIT:1><EOL>invalid |= r >= n<EOL>invalid |= s < <NUM_LIT:1><EOL>invalid |= s >= n<EOL>if invalid:<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT>hash_func = getattr(hashlib, hash_algorithm)<EOL>digest = hash_func(data).digest()<EOL>z = int_from_bytes(digest, signed=False) % n<EOL>w = inverse_mod(s, n)<EOL>u1 = (z * w) % n<EOL>u2 = (r * w) % n<EOL>hash_point = (curve_base_point * u1) + (public_key_point * u2)<EOL>if r != (hash_point.x % n):<EOL><INDENT>raise SignatureError('<STR_LIT>')<EOL><DEDENT>
Verifies an ECDSA signature in pure Python (thus slow)

: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", "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