{"record":{"id":"3c95e6eb3c1bd6fc","repo":"golang/go","slug":"invalid-scalar-length-3c95e6","errorCode":null,"errorMessage":"invalid scalar length","messagePattern":"invalid scalar length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/nistec/p256_asm.go","lineNumber":421,"sourceCode":"\tp256MovCond(&sum, &double, &sum, pointsEqual)\n\tp256MovCond(&sum, r1, &sum, r2IsInfinity)\n\tp256MovCond(&sum, r2, &sum, r1IsInfinity)\n\treturn q.Set(&sum)\n}\n\n// Double sets q = p + p, and returns q. The points may overlap.\nfunc (q *P256Point) Double(p *P256Point) *P256Point {\n\tvar double P256Point\n\tp256PointDoubleAsm(&double, p)\n\treturn q.Set(&double)\n}\n\n// ScalarBaseMult sets r = scalar * generator, where scalar is a 32-byte big\n// endian value, and returns r. If scalar is not 32 bytes long, ScalarBaseMult\n// returns an error and the receiver is unchanged.\nfunc (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) {\n\tif len(scalar) != 32 {\n\t\treturn nil, errors.New(\"invalid scalar length\")\n\t}\n\tscalarReversed := new(p256OrdElement)\n\tp256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))\n\tp256OrdReduce(scalarReversed)\n\n\tr.p256BaseMult(scalarReversed)\n\treturn r, nil\n}\n\n// ScalarMult sets r = scalar * q, where scalar is a 32-byte big endian value,\n// and returns r. If scalar is not 32 bytes long, ScalarBaseMult returns an\n// error and the receiver is unchanged.\nfunc (r *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) {\n\tif len(scalar) != 32 {\n\t\treturn nil, errors.New(\"invalid scalar length\")\n\t}\n\tscalarReversed := new(p256OrdElement)\n\tp256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/nistec/p256_asm.go#L403-L439","documentation":"P256Point.ScalarBaseMult computes r = scalar * G (generator). The scalar must be exactly 32 bytes in big-endian order; it is then reduced modulo the group order n before multiplication. Any other length is rejected outright before any computation begins, and the receiver is left unchanged.","triggerScenarios":"Calling r.ScalarBaseMult(scalar) where len(scalar) != 32.","commonSituations":"Passing a nonce or private key that was encoded with variable-length integer serialization (e.g., ASN.1/DER) instead of fixed-width 32-byte big-endian; using a big.Int.Bytes() result which strips leading zero bytes, producing fewer than 32 bytes for small values.","solutions":["Pad the scalar to exactly 32 bytes using big.Int.FillBytes(make([]byte, 32))","Validate len(scalar) == 32 before calling ScalarBaseMult","Avoid using binary.Read with variable-length buffers for scalars"],"exampleFix":"// before\nr, err := point.ScalarBaseMult(k.Bytes()) // k.Bytes() may be < 32 bytes\n\n// after\nscalar := make([]byte, 32)\nk.FillBytes(scalar) // panics if k doesn't fit; use a size check if needed\nr, err := point.ScalarBaseMult(scalar)","handlingStrategy":"validation","validationCode":"func validateScalar32(b []byte) error {\n    if len(b) != 32 {\n        return fmt.Errorf(\"scalar must be 32 bytes, got %d\", len(b))\n    }\n    return nil\n}\n\nif err := validateScalar32(scalar); err != nil { return err }\nr, err := point.ScalarBaseMult(scalar)","typeGuard":null,"tryCatchPattern":"r, err := point.ScalarBaseMult(scalar)\nif err != nil {\n    return fmt.Errorf(\"ScalarBaseMult failed: %w\", err)\n}","preventionTips":["Use big.Int.FillBytes(make([]byte, 32)) to guarantee fixed-width scalars","Avoid big.Int.Bytes() which strips leading zeros, producing short slices","Allocate fixed 32-byte buffers when reading scalars from protocol messages"],"tags":["crypto","fips140","p256","scalar","input-validation","scalar-multiplication"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}