golang/go · error

invalid scalar length

Error message

invalid scalar length

What it means

P521Point.ScalarBaseMult computes p = scalar * B (canonical P-521 generator). The scalar must be exactly p521ElementLength bytes (66 bytes) in big-endian order. P-521 field and scalar elements are 521 bits, which requires 66 bytes (with 7 padding bits in the most significant byte). Any other length is rejected.

Source

Thrown at src/crypto/internal/fips140/nistec/p521.go:414

		for i := 0; i < p521ElementLength*2; i++ {
			p521GeneratorTable[i][0] = NewP521Point().Set(base)
			for j := 1; j < 15; j++ {
				p521GeneratorTable[i][j] = NewP521Point().Add(p521GeneratorTable[i][j-1], base)
			}
			base.Double(base)
			base.Double(base)
			base.Double(base)
			base.Double(base)
		}
	})
	return p521GeneratorTable
}

// ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and
// returns p.
func (p *P521Point) ScalarBaseMult(scalar []byte) (*P521Point, error) {
	if len(scalar) != p521ElementLength {
		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 := NewP521Point()
	p.Set(NewP521Point())
	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. Pad the scalar to exactly 66 bytes using big.Int.FillBytes(make([]byte, 66))
  2. Validate len(scalar) == 66 before calling ScalarBaseMult
  3. Double-check that you are using the correct curve — P-521 scalars are 66 bytes, not 32

Example fix

// before
p, err := point.ScalarBaseMult(k.Bytes()) // likely < 66 bytes

// after
scalar := make([]byte, 66)
k.FillBytes(scalar)
p, err := point.ScalarBaseMult(scalar)
Defensive patterns

Strategy: validation

Validate before calling

const p521ScalarLen = 66

func validateP521Scalar(b []byte) error {
    if len(b) != p521ScalarLen {
        return fmt.Errorf("P-521 scalar must be %d bytes, got %d", p521ScalarLen, len(b))
    }
    return nil
}

if err := validateP521Scalar(scalar); err != nil { return err }
p, err := point.ScalarBaseMult(scalar)

Try / catch

p, err := point.ScalarBaseMult(scalar)
if err != nil {
    return fmt.Errorf("P-521 ScalarBaseMult failed: %w", err)
}

Prevention

When it happens

Trigger: Calling p.ScalarBaseMult(scalar) where len(scalar) != 66.

Common situations: Using a 64-byte (512-bit) or 32-byte scalar by mistake; encoding a P-521 private key with big.Int.Bytes() which strips leading zero bytes; passing a P-256-sized scalar to a P-521 operation due to curve confusion.

Related errors


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