golang/go · error

invalid scalar length

Error message

invalid scalar length

What it means

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.

Source

Thrown at src/crypto/internal/fips140/nistec/p256_asm.go:421

	p256MovCond(&sum, &double, &sum, pointsEqual)
	p256MovCond(&sum, r1, &sum, r2IsInfinity)
	p256MovCond(&sum, r2, &sum, r1IsInfinity)
	return q.Set(&sum)
}

// Double sets q = p + p, and returns q. The points may overlap.
func (q *P256Point) Double(p *P256Point) *P256Point {
	var double P256Point
	p256PointDoubleAsm(&double, p)
	return q.Set(&double)
}

// ScalarBaseMult sets r = scalar * generator, where scalar is a 32-byte big
// endian value, and returns r. If scalar is not 32 bytes long, ScalarBaseMult
// returns an error and the receiver is unchanged.
func (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) {
	if len(scalar) != 32 {
		return nil, errors.New("invalid scalar length")
	}
	scalarReversed := new(p256OrdElement)
	p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))
	p256OrdReduce(scalarReversed)

	r.p256BaseMult(scalarReversed)
	return r, nil
}

// ScalarMult sets r = scalar * q, where scalar is a 32-byte big endian value,
// and returns r. If scalar is not 32 bytes long, ScalarBaseMult returns an
// error and the receiver is unchanged.
func (r *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) {
	if len(scalar) != 32 {
		return nil, errors.New("invalid scalar length")
	}
	scalarReversed := new(p256OrdElement)
	p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pad the scalar to exactly 32 bytes using big.Int.FillBytes(make([]byte, 32))
  2. Validate len(scalar) == 32 before calling ScalarBaseMult
  3. Avoid using binary.Read with variable-length buffers for scalars

Example fix

// before
r, err := point.ScalarBaseMult(k.Bytes()) // k.Bytes() may be < 32 bytes

// after
scalar := make([]byte, 32)
k.FillBytes(scalar) // panics if k doesn't fit; use a size check if needed
r, err := point.ScalarBaseMult(scalar)
Defensive patterns

Strategy: validation

Validate before calling

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

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

Try / catch

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

Prevention

When it happens

Trigger: Calling r.ScalarBaseMult(scalar) where len(scalar) != 32.

Common situations: 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.

Related errors


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