golang/go · error
ecdsa: invalid signature: r is zero
Error message
ecdsa: invalid signature: r is zero
What it means
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.
Source
Thrown at src/crypto/internal/fips140/ecdsa/ecdsa.go:475
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)
if err != nil {
return err
}
if r.IsZero() == 1 {
return errors.New("ecdsa: invalid signature: r is zero")
}
s, err := bigmod.NewNat().SetBytes(sig.S, c.N)
if err != nil {
return err
}
if s.IsZero() == 1 {
return errors.New("ecdsa: invalid signature: s is zero")
}
e := bigmod.NewNat()
hashToNat(c, e, hash)
// w = s⁻¹
w := bigmod.NewNat()
inverse(c, w, s)
// p₁ = [e * s⁻¹]G
p1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N))View on GitHub (pinned to b6b368adc5)
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.
Example fix
// before
err := ecdsa.Verify(curve, pub, hash, sig)
// after: pre-check components
if isAllZero(sig.R) || isAllZero(sig.S) {
return errors.New("malformed signature")
}
err := ecdsa.Verify(curve, pub, hash, sig) Defensive patterns
Strategy: validation
Validate before calling
if allZero(sig.R) {
return errors.New("signature r is zero")
}
return ecdsa.Verify(c, pub, hash, sig) Type guard
func nonZeroR(sig *ecdsa.Signature) bool {
for _, b := range sig.R { if b != 0 { return true } }
return false
} Try / catch
if err := ecdsa.Verify(c, pub, hash, sig); err != nil {
// verification failures are final for untrusted input; do not retry
return err
} Prevention
- Only accept signatures produced by Sign/SignDeterministic.
- Validate R and S are fixed-width and non-zero at deserialization.
- Treat malformed signatures as untrusted.
When it happens
Trigger: 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.
Common situations: A corrupted, truncated, or all-zero signature; a deserialization that defaulted R to a zero slice; a forged/garbage signature from an untrusted peer.
Related errors
- ecdsa: invalid signature: s is zero
- ecdsa: signature did not verify
- ecdsa: public key does not match curve
- ecdsa: private key scalar is zero or negative
- negative coordinate
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/9e06840f3e74a327.
Report an issue: GitHub.