Error message
cryptography.exceptions.InvalidSignature
The exception is raised with no message text — the traceback ends in the bare class name (reproduced on cryptography 50.0).
Python cryptography — raised by verify()
What it means
public_key.verify(signature, data, ...) determined that the signature does not verify for this data under this key. Everything parsed; the check simply failed. Because the exception carries no detail by design, diagnosis means testing each input — key, data bytes, signature encoding, hash — separately.
Why it happens
Raw r‖s signature where DER is expected
commoncryptography's ECDSA verify() takes ASN.1 DER. A 64-byte raw signature from WebCrypto, JWS, or another library's "raw" mode will (at best) fail to parse and (at worst, if padded oddly) simply never verify.
The data bytes differ
commonstr vs bytes encoding differences, a trailing newline, JSON re-serialization with different key order or whitespace — verify() signs/verifies exact bytes, and "semantically identical" is not identical.
Double hashing via Prehashed misuse
commonverify(sig, data, ec.ECDSA(hashes.SHA256())) hashes data itself. Passing an already-computed digest without utils.Prehashed hashes the digest again — a top-3 cause of mysterious verification failures.
Wrong key or wrong hash
occasionalA rotated or mismatched public key, or verifying with SHA-256 what was signed over SHA-384. The hash is part of the signature scheme, not a free parameter.
How to fix it
- 1.
Convert raw signatures to DER
If the signature is 64 bytes (P-256), split it into r and s and re-encode as DER before verifying.
python from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature r = int.from_bytes(raw_sig[:32], "big") s = int.from_bytes(raw_sig[32:], "big") der_sig = encode_dss_signature(r, s) public_key.verify(der_sig, message, ec.ECDSA(hashes.SHA256())) - 2.
Use Prehashed for pre-computed digests
When you hold the digest instead of the message, say so explicitly — otherwise the library hashes your hash.
python from cryptography.hazmat.primitives.asymmetric import utils public_key.verify( der_sig, digest_bytes, # already SHA-256(message) ec.ECDSA(utils.Prehashed(hashes.SHA256())), ) - 3.
Pin down which input is wrong
Paste key, message and signature into the error explainer below: it tests the usual mismatch hypotheses — wrong hash, raw vs DER, double hashing, high-S normalization, wrong curve — and names the one that makes your signature verify.