{"record":{"id":"9e06840f3e74a327","repo":"golang/go","slug":"ecdsa-invalid-signature-r-is-zero","errorCode":null,"errorMessage":"ecdsa: invalid signature: r is zero","messagePattern":"ecdsa: invalid signature: r is zero","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/ecdsa/ecdsa.go","lineNumber":475,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif r.IsZero() == 1 {\n\t\treturn errors.New(\"ecdsa: invalid signature: r is zero\")\n\t}\n\ts, err := bigmod.NewNat().SetBytes(sig.S, c.N)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif s.IsZero() == 1 {\n\t\treturn errors.New(\"ecdsa: invalid signature: s is zero\")\n\t}\n\n\te := bigmod.NewNat()\n\thashToNat(c, e, hash)\n\n\t// w = s⁻¹\n\tw := bigmod.NewNat()\n\tinverse(c, w, s)\n\n\t// p₁ = [e * s⁻¹]G\n\tp1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N))","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/ecdsa/ecdsa.go#L457-L493","documentation":"Thrown by fips140/ecdsa.verifyGeneric (the FIPS 186-5 §6.4.2 verifier) when the signature's r component is zero after being parsed with SetBytes into the curve order field. An r of zero is invalid by FIPS 186-5 and would make the verification equation trivially broken.","triggerScenarios":"Verifying a Signature whose R field is all zeros (or reduces to zero mod n). SetBytes(sig.R, c.N) must first succeed (R < n), then the zero check fires.","commonSituations":"A corrupted, truncated, or all-zero signature; a deserialization that defaulted R to a zero slice; a forged/garbage signature from an untrusted peer.","solutions":["Reject signatures where sig.R is all-zero before calling Verify.","Re-serialize/transport the signature correctly (both R and S fixed-width).","Treat verification errors as untrusted input and do not retry with the same data."],"exampleFix":"// before\nerr := ecdsa.Verify(curve, pub, hash, sig)\n\n// after: pre-check components\nif isAllZero(sig.R) || isAllZero(sig.S) {\n    return errors.New(\"malformed signature\")\n}\nerr := ecdsa.Verify(curve, pub, hash, sig)","handlingStrategy":"validation","validationCode":"if allZero(sig.R) {\n    return errors.New(\"signature r is zero\")\n}\nreturn ecdsa.Verify(c, pub, hash, sig)","typeGuard":"func nonZeroR(sig *ecdsa.Signature) bool {\n    for _, b := range sig.R { if b != 0 { return true } }\n    return false\n}","tryCatchPattern":"if err := ecdsa.Verify(c, pub, hash, sig); err != nil {\n    // verification failures are final for untrusted input; do not retry\n    return err\n}","preventionTips":["Only accept signatures produced by Sign/SignDeterministic.","Validate R and S are fixed-width and non-zero at deserialization.","Treat malformed signatures as untrusted."],"tags":["go","crypto","fips","ecdsa","verification","signature"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}