{"record":{"id":"b7126cd586cbdf17","repo":"golang/go","slug":"negative-coordinate-b7126c","errorCode":null,"errorMessage":"negative coordinate","messagePattern":"negative coordinate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/elliptic/nistec.go","lineNumber":143,"sourceCode":"func (curve *nistCurve[Point]) IsOnCurve(x, y *big.Int) bool {\n\t// IsOnCurve is documented to reject (0, 0), the conventional point at\n\t// infinity, which however is accepted by pointFromAffine.\n\tif x.Sign() == 0 && y.Sign() == 0 {\n\t\treturn false\n\t}\n\t_, err := curve.pointFromAffine(x, y)\n\treturn err == nil\n}\n\nfunc (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, err error) {\n\t// (0, 0) is by convention the point at infinity, which can't be represented\n\t// in affine coordinates. See Issue 37294.\n\tif x.Sign() == 0 && y.Sign() == 0 {\n\t\treturn curve.newPoint(), nil\n\t}\n\t// Reject values that would not get correctly encoded.\n\tif x.Sign() < 0 || y.Sign() < 0 {\n\t\treturn p, errors.New(\"negative coordinate\")\n\t}\n\tif x.BitLen() > curve.params.BitSize || y.BitLen() > curve.params.BitSize {\n\t\treturn p, errors.New(\"overflowing coordinate\")\n\t}\n\t// Encode the coordinates and let SetBytes reject invalid points.\n\tbyteLen := (curve.params.BitSize + 7) / 8\n\tbuf := make([]byte, 1+2*byteLen)\n\tbuf[0] = 4 // uncompressed point\n\tx.FillBytes(buf[1 : 1+byteLen])\n\ty.FillBytes(buf[1+byteLen : 1+2*byteLen])\n\treturn curve.newPoint().SetBytes(buf)\n}\n\nfunc (curve *nistCurve[Point]) pointToAffine(p Point) (x, y *big.Int) {\n\tout := p.Bytes()\n\tif len(out) == 1 && out[0] == 0 {\n\t\t// This is the encoding of the point at infinity, which the affine\n\t\t// coordinates API represents as (0, 0) by convention.","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/elliptic/nistec.go#L125-L161","documentation":"Thrown by nistCurve.pointFromAffine (nistec.go:143) when either X or Y of a point passed to the nistec backend is negative. This is the elliptic-layer sibling of ecdsa error 241: it guards the same fixed-width encoding, but at the elliptic.Curve abstraction level used by crypto/ecdsa, crypto/tls, and crypto/x509.","triggerScenarios":"Reached via elliptic curve operations (Unmarshal, Add, ScalarMult on a nistCurve) and indirectly through ecdsa. Triggered when x.Sign() < 0 || y.Sign() < 0 after excluding the (0,0) infinity convention. Happens with hand-built points or arithmetic that left a coordinate negative.","commonSituations":"Custom elliptic-curve code using big.Int subtraction without a final Mod into the field; importing points from formats that permit a sign; interop with a library producing signed field elements.","solutions":["Reduce coordinates modulo the field prime (x.Mod(x, P)) before any elliptic curve call.","Parse points with elliptic.Unmarshal / standard ASN.1 rather than constructing them from raw big.Int.","Validate x.Sign() >= 0 && y.Sign() >= 0 at the trust boundary."],"exampleFix":"// before\nx := new(big.Int).Sub(a, b) // may be negative\npx, py := curve.ScalarMult(x, y, k) // -> error 253\n\n// after\nP := curve.Params().P\nx.Mod(x, P)\npx, py := curve.ScalarMult(x, y, k)","handlingStrategy":"validation","validationCode":"if x.Sign() < 0 || y.Sign() < 0 {\n    return errors.New(\"elliptic coordinates must be non-negative\")\n}","typeGuard":"func nonNegativeEC(x, y *big.Int) bool {\n    return x != nil && y != nil && x.Sign() >= 0 && y.Sign() >= 0\n}","tryCatchPattern":null,"preventionTips":["Reduce coordinates modulo the field prime before elliptic curve operations.","Prefer elliptic.Unmarshal over constructing points from raw big.Int.","Validate coordinates received from external sources."],"tags":["go","crypto","elliptic","validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}