golang/go · error
invalid scalar length
Error message
invalid scalar length
What it means
Generated from generate.go:548. Thrown by ScalarBaseMult when the scalar is not exactly ElementLength bytes for the curve. Fixed-size scalars are required by the constant-time comb implementation; variable-length scalars are not supported.
Source
Thrown at src/crypto/internal/fips140/nistec/generate.go:548
for i := 0; i < {{.p}}ElementLength*2; i++ {
{{.p}}GeneratorTable[i][0] = New{{.P}}Point().Set(base)
for j := 1; j < 15; j++ {
{{.p}}GeneratorTable[i][j] = New{{.P}}Point().Add({{.p}}GeneratorTable[i][j-1], base)
}
base.Double(base)
base.Double(base)
base.Double(base)
base.Double(base)
}
})
return {{.p}}GeneratorTable
}
// ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and
// returns p.
func (p *{{.P}}Point) ScalarBaseMult(scalar []byte) (*{{.P}}Point, error) {
if len(scalar) != {{.p}}ElementLength {
return nil, errors.New("invalid scalar length")
}
tables := p.generatorTable()
// This is also a scalar multiplication with a four-bit window like in
// ScalarMult, but in this case the doublings are precomputed. The value
// [windowValue]G added at iteration k would normally get doubled
// (totIterations-k)×4 times, but with a larger precomputation we can
// instead add [2^((totIterations-k)×4)][windowValue]G and avoid the
// doublings between iterations.
t := New{{.P}}Point()
p.Set(New{{.P}}Point())
tableIndex := len(tables) - 1
for _, byte := range scalar {
windowValue := byte >> 4
tables[tableIndex].Select(t, windowValue)
p.Add(p, t)
tableIndex--
View on GitHub (pinned to b6b368adc5)
Solutions
- Right-pad the scalar to ElementLength with FillBytes before calling ScalarBaseMult.
- Reduce the scalar mod n where appropriate (note: ScalarBaseMult treats the input as fixed-size, not mod-reduced).
- Confirm the byte slice is raw big-endian, not hex/base64.
- Use the curve-matching scalar size constant rather than a hard-coded number.
Example fix
// before
p, err := pt.ScalarBaseMult(k.Bytes()) // variable length
// after
buf := make([]byte, p256ElementLength)
if !k.FillBytes(buf) { return errors.New("scalar too large") }
p, err := pt.ScalarBaseMult(buf) Defensive patterns
Strategy: validation
Validate before calling
// Right-pad the scalar to ElementLen with FillBytes.
buf := make([]byte, elementLength)
if !k.FillBytes(buf) {
return errors.New("scalar too large")
} Type guard
func isFixedLengthScalar(b []byte, elLen int) bool { return len(b) == elLen } Try / catch
p, err := pt.ScalarBaseMult(scalar)
if err != nil {
return fmt.Errorf("scalar rejected (len=%d): %w", len(scalar), err)
} Prevention
- Use big.Int.FillBytes (fixed size) instead of Bytes (variable size).
- Pin the curve's ElementLen constant rather than hard-coding a number.
- Decode hex/base64 into a fixed-length buffer before passing.
When it happens
Trigger: Passing a 31-byte scalar to P-256 (expects 32), a big.Int.Bytes() output that dropped a leading zero, a hex string instead of raw bytes, or a scalar sized for a different curve.
Common situations: big.Int -> []byte via Bytes() (variable length) instead of FillBytes (fixed length), reusing a scalar across curves, or hash-truncated nonces that land short of ElementLength.
Related errors
- invalid {{ .Element }} encoding
- invalid {{.P}} compressed point encoding
- invalid {{.P}} point encoding
- {{.P}} point not on curve
- {{.P}} point is the point at infinity
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/eae0857954206587.
Report an issue: GitHub.