golang/go · error

ecdsa: public key point is the infinity

Error message

ecdsa: public key point is the infinity

What it means

Thrown by pointToAffine (ecdsa.go:643) when the nistec point encodes to a single 0x00 byte — the standard encoding of the point at infinity (identity element). An ECDSA public key must never be the identity; such a key is invalid and cannot be used for verification, since the identity has no discrete-log.

Source

Thrown at src/crypto/ecdsa/ecdsa.go:643

		return nil, errors.New("negative coordinate")
	}
	if x.BitLen() > bitSize || y.BitLen() > bitSize {
		return nil, errors.New("overflowing coordinate")
	}
	// Encode the coordinates and let [ecdsa.NewPublicKey] reject invalid points.
	byteLen := (bitSize + 7) / 8
	buf := make([]byte, 1+2*byteLen)
	buf[0] = 4 // uncompressed point
	x.FillBytes(buf[1 : 1+byteLen])
	y.FillBytes(buf[1+byteLen : 1+2*byteLen])
	return buf, nil
}

// pointToAffine is used to convert a nistec Bytes encoding to a PublicKey.
func pointToAffine(curve elliptic.Curve, p []byte) (x, y *big.Int, err error) {
	if len(p) == 1 && p[0] == 0 {
		// This is the encoding of the point at infinity.
		return nil, nil, errors.New("ecdsa: public key point is the infinity")
	}
	byteLen := (curve.Params().BitSize + 7) / 8
	x = new(big.Int).SetBytes(p[1 : 1+byteLen])
	y = new(big.Int).SetBytes(p[1+byteLen:])
	return x, y, nil
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Reject all-zero or single-0x00 point encodings before constructing the PublicKey.
  2. Use ecdsa.NewPublicKey / standard ASN.1 parsing which validates points; never build PublicKey{X:0,Y:0} by hand.
  3. Verify the peer's public key is on the curve and is not the identity as part of key validation at the trust boundary.

Example fix

// before
pub := ecdsa.PublicKey{Curve: elliptic.P256(), X: big.NewInt(0), Y: big.NewInt(0)}
ok := ecdsa.Verify(&pub, hash, r, s) // -> error 243

// after
parsed, err := x509.ParsePKIXPublicKey(derBytes) // validates point
if err != nil { return err }
pub := parsed.(*ecdsa.PublicKey)
Defensive patterns

Strategy: validation

Validate before calling

// reject identity / all-zero point before constructing a PublicKey
isZero := func(z *big.Int) bool { return z == nil || z.Sign() == 0 }
if isZero(pub.X) && isZero(pub.Y) {
    return errors.New("public key must not be the point at infinity")
}

Type guard

func isIdentityPoint(pub *ecdsa.PublicKey) bool {
    return pub.X.Sign() == 0 && pub.Y.Sign() == 0
}

Prevention

When it happens

Trigger: Reached when converting a FIPS nistec point back to affine coordinates (line 566 in parsePublicKey / verification paths). Happens when the underlying point object is the zero/identity point — e.g. a malformed public key whose decoded coordinates happen to satisfy y^2 = x^3 + ax + b at the identity, or arithmetic that produced the identity (adding a point to its inverse).

Common situations: Parsing a public key that was set to all-zero bytes, importing a key from a peer that sent a degenerate point, or test vectors that accidentally encode the identity.

Related errors


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