golang/go · error

invalid {{.P}} point encoding

Error message

invalid {{.P}} point encoding

What it means

Generated from generate.go:239. Thrown when SetBytes on a NIST point falls through all recognized cases (uncompressed 0x04 of length 1+2*ElementLength, compressed 0x02/0x03, or infinity 0x00). Any other type byte or wrong length lands here.

Source

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

		y := {{.p}}Polynomial(new({{.Element}}), x)
		if !{{.p}}Sqrt(y, y) {
			return nil, errors.New("invalid {{.P}} compressed point encoding")
		}

		// Select the positive or negative root, as indicated by the least
		// significant bit, based on the encoding type byte.
		otherRoot := new({{.Element}})
		otherRoot.Sub(otherRoot, y)
		cond := y.Bytes()[{{.p}}ElementLength-1]&1 ^ b[0]&1
		y.Select(otherRoot, y, int(cond))

		p.x.Set(x)
		p.y.Set(y)
		p.z.One()
		return p, nil

	default:
		return nil, errors.New("invalid {{.P}} point encoding")
	}
}


var _{{.p}}B *{{.Element}}
var _{{.p}}BOnce sync.Once

func {{.p}}B() *{{.Element}} {
	_{{.p}}BOnce.Do(func() {
		_{{.p}}B, _ = new({{.Element}}).SetBytes({{.B}})
	})
	return _{{.p}}B
}

// {{.p}}Polynomial sets y2 to x³ - 3x + b, and returns y2.
func {{.p}}Polynomial(y2, x *{{.Element}}) *{{.Element}} {
	y2.Square(x)
	y2.Mul(y2, x)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Wrap raw (x,y) coordinates in a 0x04-prefixed uncompressed SEC1 buffer of length 1+2*ElementLength.
  2. Decode hex/base64 into raw bytes before calling SetBytes.
  3. Strip any length prefix or framing the parser does not expect.
  4. If the source emits hybrid (0x06/0x07) encoding, convert to 0x04 uncompressed first.

Example fix

// before
p, err := nistec.NewP256Point().SetBytes(raw) // raw is x||y with no 0x04
// after
buf := make([]byte, 1+2*p256ElementLength)
buf[0] = 4
copy(buf[1:], raw)
p, err := nistec.NewP256Point().SetBytes(buf)
Defensive patterns

Strategy: validation

Validate before calling

// Wrap raw (x,y) in uncompressed SEC1 form before SetBytes.
buf := make([]byte, 1+2*elementLength)
buf[0] = 4
copy(buf[1:1+elementLength], x)
copy(buf[1+elementLength:], y)

Type guard

func isSEC1Point(b []byte, elLen int) bool {
    switch {
    case len(b) == 1 && b[0] == 0:
        return true
    case len(b) == 1+2*elLen && b[0] == 4:
        return true
    case len(b) == 1+elLen && (b[0] == 2 || b[0] == 3):
        return true
    }
    return false
}

Try / catch

p, err := curve.NewPoint().SetBytes(b)
if err != nil {
    return fmt.Errorf("unrecognized point encoding (prefix=0x%x, len=%d): %w", b[0], len(b), err)
}

Prevention

When it happens

Trigger: Input with an unrecognized leading byte (e.g. 0x06/0x07 hybrid, 0x01), a length that matches no recognized encoding, an un-decoded hex string, or a multi-buffer concatenation.

Common situations: Hybrid SEC1 encodings (deprecated, unsupported), wrong-length buffer after a slice mishap, raw coordinate pairs not wrapped in 0x04, or assuming the parser accepts COSE/JWK coordinate arrays.

Related errors


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