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

  1. Reject signatures where sig.R is all-zero before calling Verify.
  2. Re-serialize/transport the signature correctly (both R and S fixed-width).
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/9e06840f3e74a327. Report an issue: GitHub.