Inputs are the public key, the message (or its digest), the signature and the algorithm with its parameters; the output is valid or invalid. A strict verifier also rejects malformed input: non-minimal DER, r or s outside 1…n−1, an EdDSA S not below the group order, raw signatures of the wrong length, points that are not on the curve and keys of the wrong type.
Most production "invalid signature" errors are not cryptographic: different bytes were signed (re-serialized JSON, changed whitespace or line endings, a missing trailing newline), a different hash was used, a DER signature reached a raw verifier or vice versa, the curve or the PSS salt length differs, or the wrong key was selected. Check each input separately; the signature verifier shows which curve, hash and encoding it used.
Security rules that prevent real breaks: fix the algorithm on the verifier side instead of reading it from the message (JWT alg, RFC 8725 §3.1); verify before parsing or acting on the payload; verify the binding between key and identity (certificate path validation, JWKS kid, known_hosts); and for consensus systems, pin one verification rule set, since libraries disagree on edge cases such as EdDSA cofactored checks.