golang/go · error
ecdsa: public key does not match curve
Error message
ecdsa: public key does not match curve
What it means
Thrown by fips140/ecdsa.Verify when the public key's curve does not match the operation context curve (pub.curve != c.curve). Verification requires the curve handle, the public key, and (implicitly) the signature to all correspond to the same curve.
Source
Thrown at src/crypto/internal/fips140/ecdsa/ecdsa.go:452
for i := len(b) - 1; i >= 0; i-- {
b[i] >>= shift
if i > 0 {
b[i] |= b[i-1] << (8 - shift)
}
}
return b
}
// Verify verifies the signature, sig, of hash (which should be the result of
// hashing a larger message) using the public key, pub. If the hash is longer
// than the bit-length of the private key's curve order, the hash will be
// truncated to that length.
//
// The inputs are not considered confidential, and may leak through timing side
// channels, or if an attacker has control of part of the inputs.
func Verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
if pub.curve != c.curve {
return errors.New("ecdsa: public key does not match curve")
}
if len(hash) == 0 {
return errors.New("ecdsa: hash cannot be empty")
}
fips140.RecordApproved()
fipsSelfTest()
return verify(c, pub, hash, sig)
}
func verifyGeneric[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
// FIPS 186-5, Section 6.4.2
Q, err := c.newPoint().SetBytes(pub.q)
if err != nil {
return err
}
r, err := bigmod.NewNat().SetBytes(sig.R, c.N)View on GitHub (pinned to b6b368adc5)
Solutions
- Select c from the same curve the public key was constructed with.
- Assert pub.curve == c before calling Verify.
- Carry the curve with the public key and pass it as c.
Example fix
// before err := ecdsa.Verify(ecdsa.P256(), p384Pub, hash, sig) // after err := ecdsa.Verify(ecdsa.P384(), p384Pub, hash, sig)
Defensive patterns
Strategy: validation
Validate before calling
if pub.Curve() != c.Curve() {
return errors.New("public key curve differs from verify context")
}
return ecdsa.Verify(c, pub, hash, sig) Type guard
func keyMatchesVerifyCurve(c *ecdsa.Curve, pub *ecdsa.PublicKey) bool {
return pub.Curve() == c.Curve()
} Prevention
- Take c from pub.Curve() rather than a default constant.
- Persist the curve alongside the public key.
- Reject signatures whose declared curve differs from the key's.
When it happens
Trigger: Calling Verify(c, pub, hash, sig) where c and pub belong to different curves.
Common situations: Verifying a signature with the wrong curve handle, mixing keys from a P-256 and P-384 system, or a verifier that picks a default curve constant.
Related errors
- ecdsa: private key does not match curve
- ecdsa: invalid signature: r is zero
- ecdsa: invalid signature: s is zero
- ecdsa: signature did not verify
- ecdsa: private key scalar is zero or negative
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/1e0dbd570cf679d3.
Report an issue: GitHub.