{"record":{"id":"1e0dbd570cf679d3","repo":"golang/go","slug":"ecdsa-public-key-does-not-match-curve","errorCode":null,"errorMessage":"ecdsa: public key does not match curve","messagePattern":"ecdsa: public key does not match curve","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/ecdsa/ecdsa.go","lineNumber":452,"sourceCode":"\tfor i := len(b) - 1; i >= 0; i-- {\n\t\tb[i] >>= shift\n\t\tif i > 0 {\n\t\t\tb[i] |= b[i-1] << (8 - shift)\n\t\t}\n\t}\n\treturn b\n}\n\n// Verify verifies the signature, sig, of hash (which should be the result of\n// hashing a larger message) using the public key, pub. If the hash is longer\n// than the bit-length of the private key's curve order, the hash will be\n// truncated to that length.\n//\n// The inputs are not considered confidential, and may leak through timing side\n// channels, or if an attacker has control of part of the inputs.\nfunc Verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {\n\tif pub.curve != c.curve {\n\t\treturn errors.New(\"ecdsa: public key does not match curve\")\n\t}\n\tif len(hash) == 0 {\n\t\treturn errors.New(\"ecdsa: hash cannot be empty\")\n\t}\n\tfips140.RecordApproved()\n\tfipsSelfTest()\n\treturn verify(c, pub, hash, sig)\n}\n\nfunc verifyGeneric[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {\n\t// FIPS 186-5, Section 6.4.2\n\n\tQ, err := c.newPoint().SetBytes(pub.q)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tr, err := bigmod.NewNat().SetBytes(sig.R, c.N)","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/ecdsa/ecdsa.go#L434-L470","documentation":"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.","triggerScenarios":"Calling Verify(c, pub, hash, sig) where c and pub belong to different curves.","commonSituations":"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.","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."],"exampleFix":"// before\nerr := ecdsa.Verify(ecdsa.P256(), p384Pub, hash, sig)\n\n// after\nerr := ecdsa.Verify(ecdsa.P384(), p384Pub, hash, sig)","handlingStrategy":"validation","validationCode":"if pub.Curve() != c.Curve() {\n    return errors.New(\"public key curve differs from verify context\")\n}\nreturn ecdsa.Verify(c, pub, hash, sig)","typeGuard":"func keyMatchesVerifyCurve(c *ecdsa.Curve, pub *ecdsa.PublicKey) bool {\n    return pub.Curve() == c.Curve()\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["go","crypto","fips","ecdsa","verification","curve-mismatch"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}