golang/go · error
negative coordinate
Error message
negative coordinate
What it means
Thrown by pointFromAffine (ecdsa.go:625) when either the X or Y coordinate of an ECDSA PublicKey has a negative sign. ECDSA point coordinates are field elements represented as non-negative big.Int values; a negative value indicates corruption or misuse of math/big (e.g. a subtraction that went negative, or an externally-constructed key with bogus coordinates).
Source
Thrown at src/crypto/ecdsa/ecdsa.go:625
if size > maxScalarSize {
return nil, errors.New("ecdsa: internal error: curve size too large")
}
D := priv.D.FillBytes(make([]byte, size, maxScalarSize))
return privateKeyCache.Get(priv, func() (*ecdsa.PrivateKey, error) {
return ecdsa.NewPrivateKey(c, D, Q)
}, func(k *ecdsa.PrivateKey) bool {
return subtle.ConstantTimeCompare(k.PublicKey().Bytes(), Q) == 1 &&
subtle.ConstantTimeCompare(k.Bytes(), D) == 1
})
}
// pointFromAffine is used to convert the PublicKey to a nistec SetBytes input.
func pointFromAffine(curve elliptic.Curve, x, y *big.Int) ([]byte, error) {
bitSize := curve.Params().BitSize
// Reject values that would not get correctly encoded.
if x.Sign() < 0 || y.Sign() < 0 {
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")View on GitHub (pinned to b6b368adc5)
Solutions
- Always reduce coordinates with x.Mod(x, P) (where P is the field prime) before building the PublicKey so the sign is non-negative.
- Load public keys only through x509.ParsePKIXPublicKey / cryptobyte ASN.1 parsing rather than constructing PublicKey{X,Y} directly.
- Validate pub.X.Sign() >= 0 && pub.Y.Sign() >= 0 before invoking ecdsa.Verify*.
Example fix
// before
x := new(big.Int).Sub(a, b) // may be negative
pub := ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
ok := ecdsa.Verify(&pub, hash, r, s) // -> error 241 via pointFromAffine
// after
P := elliptic.P256().Params().P
x := new(big.Int).Sub(a, b)
x.Mod(x, P) // now in [0, P)
pub := ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y} Defensive patterns
Strategy: validation
Validate before calling
if pub.X.Sign() < 0 || pub.Y.Sign() < 0 {
return errors.New("public key coordinates must be non-negative")
} Type guard
func nonNegativeCoords(pub *ecdsa.PublicKey) bool {
return pub != nil && pub.X != nil && pub.Y != nil && pub.X.Sign() >= 0 && pub.Y.Sign() >= 0
} Prevention
- Reduce all big.Int coordinates modulo the field prime before building a PublicKey.
- Prefer standard parsing (x509/cryptobyte) over manual coordinate construction.
- Validate coordinates at the trust boundary for keys received over the wire.
When it happens
Trigger: Reached via privateKeyToFIPS (line 592) and parsePublicKey (line 582) — any Sign/Verify path that converts a PublicKey to the FIPS nistec representation. Triggered when pub.X.Sign() < 0 || pub.Y.Sign() < 0, e.g. coordinates produced by ModInverse/Sub without a final Mod into the field, or hand-built keys with negative components.
Common situations: Custom curve arithmetic that uses big.Int subtraction without taking a positive modulus; importing coordinates from JSON/ASN.1 that allowed a leading sign bit; porting code from a library that permits signed coordinates.
Related errors
- ecdsa: private key scalar is zero or negative
- overflowing coordinate
- ecdsa: public key point is the infinity
- crypto/ecdsa: use of custom curves is not allowed in FIPS 14
- zero parameter
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/6dc611445f675d2f.
Report an issue: GitHub.