golang/go · error

{{.P}} point is the point at infinity

Error message

{{.P}} point is the point at infinity

What it means

Generated from generate.go:312. Thrown by BytesX when the point is the identity (z == 0), because the point at infinity has no affine x-coordinate to encode. Distinct from Bytes() which has a defined infinity encoding.

Source

Thrown at src/crypto/internal/fips140/nistec/generate.go:312

	buf := append(out[:0], 4)
	buf = append(buf, x.Bytes()...)
	buf = append(buf, y.Bytes()...)
	return buf
}

// BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1,
// Version 2.0, Section 2.3.5, or an error if p is the point at infinity.
func (p *{{.P}}Point) BytesX() ([]byte, error) {
	// This function is outlined to make the allocations inline in the caller
	// rather than happen on the heap.
	var out [{{.p}}ElementLength]byte
	return p.bytesX(&out)
}

func (p *{{.P}}Point) bytesX(out *[{{.p}}ElementLength]byte) ([]byte, error) {
	if p.z.IsZero() == 1 {
		return nil, errors.New("{{.P}} point is the point at infinity")
	}

	zinv := new({{.Element}}).Invert(p.z)
	x := new({{.Element}}).Mul(p.x, zinv)

	return append(out[:0], x.Bytes()...), nil
}

// BytesCompressed returns the compressed or infinity encoding of p, as
// specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the
// point at infinity is shorter than all other encodings.
func (p *{{.P}}Point) BytesCompressed() []byte {
	// This function is outlined to make the allocations inline in the caller
	// rather than happen on the heap.
	var out [1 + {{.p}}ElementLength]byte
	return p.bytesCompressed(&out)
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Check the point is not the identity before calling BytesX (e.g. via Bytes() length or an IsInfinity helper).
  2. In ECDH, reject the peer's identity point explicitly to avoid leaking the shared secret computation.
  3. Guard scalar-multiplication results: if the identity is an unexpected outcome, return an error before serializing.
  4. Initialize points via SetBytes / New* rather than leaving the zero value when an affine coordinate will be requested.

Example fix

// before
x, err := p.BytesX() // panics path when p is identity
// after
if p.Bytes()[0] == 0 { // infinity encoding is short / starts with 0x00
    return errors.New("refusing to extract x of identity point")
}
x, err := p.BytesX()
Defensive patterns

Strategy: type-guard

Validate before calling

// Detect the point at infinity before extracting x.
if len(p.Bytes()) == 1 { // infinity encoding is a single 0x00 byte
    return errors.New("point is identity; no affine x")
}

Type guard

func isInfinity(p *nistec.P256Point) bool {
    enc := p.Bytes()
    return len(enc) == 1 && enc[0] == 0
}

Try / catch

x, err := p.BytesX()
if err != nil && strings.Contains(err.Error(), "point at infinity") {
    return errors.New("refusing x of identity point")
}

Prevention

When it happens

Trigger: Calling BytesX after a scalar multiplication that produced the identity (e.g. multiplying a point by its order), on a freshly zero-initialized point that was never set, or on the additive identity result of P + (-P).

Common situations: ECDSA/ECIES path that assumes a non-identity result, ECDH where the peer sent the identity point (invalid-curve/small-subgroup attack), or uninitialized point defaults.

Related errors


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