{"record":{"id":"7f16684696f9e1fe","repo":"golang/go","slug":"p521-point-is-the-point-at-infinity","errorCode":null,"errorMessage":"P521 point is the point at infinity","messagePattern":"P521 point is the point at infinity","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/nistec/p521.go","lineNumber":178,"sourceCode":"\n\tbuf := append(out[:0], 4)\n\tbuf = append(buf, x.Bytes()...)\n\tbuf = append(buf, y.Bytes()...)\n\treturn buf\n}\n\n// BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1,\n// Version 2.0, Section 2.3.5, or an error if p is the point at infinity.\nfunc (p *P521Point) BytesX() ([]byte, error) {\n\t// This function is outlined to make the allocations inline in the caller\n\t// rather than happen on the heap.\n\tvar out [p521ElementLength]byte\n\treturn p.bytesX(&out)\n}\n\nfunc (p *P521Point) bytesX(out *[p521ElementLength]byte) ([]byte, error) {\n\tif p.z.IsZero() == 1 {\n\t\treturn nil, errors.New(\"P521 point is the point at infinity\")\n\t}\n\n\tzinv := new(fiat.P521Element).Invert(p.z)\n\tx := new(fiat.P521Element).Mul(p.x, zinv)\n\n\treturn append(out[:0], x.Bytes()...), nil\n}\n\n// BytesCompressed returns the compressed or infinity encoding of p, as\n// specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the\n// point at infinity is shorter than all other encodings.\nfunc (p *P521Point) BytesCompressed() []byte {\n\t// This function is outlined to make the allocations inline in the caller\n\t// rather than happen on the heap.\n\tvar out [1 + p521ElementLength]byte\n\treturn p.bytesCompressed(&out)\n}\n","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/nistec/p521.go#L160-L196","documentation":"P521Point.BytesX() returns the SEC 1 x-coordinate encoding of a P-521 point and rejects the identity element (z == 0). The point at infinity has no affine representation, so extracting its x-coordinate is undefined. This is the P-521 counterpart of errors 400/409.","triggerScenarios":"Calling p.BytesX() on a P521Point whose z coordinate is zero — the result of ScalarMult with a zero scalar, an uninitialized point, or a point added to its inverse.","commonSituations":"P-521 ECDH with a malicious identity public key; ECDSA-P521 where the nonce yields infinity; uninitialized P521Point from NewP521Point().","solutions":["Check p.Bytes() for the 1-byte 0x00 infinity encoding before calling BytesX","Validate scalar multiplication results before coordinate extraction","Reject identity points from untrusted peers"],"exampleFix":"// before\nx, err := p521Point.BytesX()\n\n// after\nif enc := p521Point.Bytes(); len(enc) == 1 && enc[0] == 0 {\n    return errors.New(\"P-521 identity point; no x-coordinate\")\n}\nx, err := p521Point.BytesX()","handlingStrategy":"validation","validationCode":"func mustNotBeInfinityP521(p *nistec.P521Point) error {\n    enc := p.Bytes()\n    if len(enc) == 1 && enc[0] == 0 {\n        return errors.New(\"P-521 point is identity\")\n    }\n    return nil\n}\n\nif err := mustNotBeInfinityP521(point); err != nil { return err }\nx, err := point.BytesX()","typeGuard":null,"tryCatchPattern":"x, err := p521Point.BytesX()\nif err != nil {\n    return fmt.Errorf(\"cannot extract P-521 x-coordinate: %w\", err)\n}","preventionTips":["Check for the identity point before extracting P-521 coordinates","Validate the shared secret in P-521 ECDH is not infinity","Ensure scalars are non-zero and properly bounded"],"tags":["crypto","fips140","p521","elliptic-curve","point-at-infinity"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}