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

  1. Right-pad the scalar to ElementLength with FillBytes before calling ScalarBaseMult.
  2. Reduce the scalar mod n where appropriate (note: ScalarBaseMult treats the input as fixed-size, not mod-reduced).
  3. Confirm the byte slice is raw big-endian, not hex/base64.
  4. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/eae0857954206587. Report an issue: GitHub.