golang/go · error
invalid scalar length
Error message
invalid scalar length
What it means
p256OrdElement.SetBytes requires exactly 32 bytes of big-endian input representing a P-256 scalar. The value is then conditionally reduced into [0, ord(G)-1]. Any length other than 32 is rejected because the P-256 scalar field has a fixed 256-bit width and no variable-length encoding is supported.
Source
Thrown at src/crypto/internal/fips140/nistec/p256.go:402
return q
}
// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
func (q *P256Point) Select(p1, p2 *P256Point, cond int) *P256Point {
q.x.Select(&p1.x, &p2.x, cond)
q.y.Select(&p1.y, &p2.y, cond)
q.z.Select(&p1.z, &p2.z, cond)
return q
}
// p256OrdElement is a P-256 scalar field element in [0, ord(G)-1]
// as four uint64 limbs in little-endian order.
type p256OrdElement [4]uint64
// SetBytes sets s to the big-endian value of x, reducing it as necessary.
func (s *p256OrdElement) SetBytes(x []byte) (*p256OrdElement, error) {
if len(x) != 32 {
return nil, errors.New("invalid scalar length")
}
s[0] = byteorder.BEUint64(x[24:])
s[1] = byteorder.BEUint64(x[16:])
s[2] = byteorder.BEUint64(x[8:])
s[3] = byteorder.BEUint64(x[:])
// Ensure s is in the range [0, ord(G)-1]. Since 2 * ord(G) > 2²⁵⁶, we can
// just conditionally subtract ord(G), keeping the result if it doesn't
// underflow.
t0, b := bits.Sub64(s[0], 0xf3b9cac2fc632551, 0)
t1, b := bits.Sub64(s[1], 0xbce6faada7179e84, b)
t2, b := bits.Sub64(s[2], 0xffffffffffffffff, b)
t3, b := bits.Sub64(s[3], 0xffffffff00000000, b)
tMask := b - 1 // zero if subtraction underflowed
s[0] ^= (t0 ^ s[0]) & tMask
s[1] ^= (t1 ^ s[1]) & tMask
s[2] ^= (t2 ^ s[2]) & tMaskView on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the scalar byte slice is exactly 32 bytes before calling SetBytes
- If the scalar arrives as a big.Int, use bigInt.FillBytes(make([]byte, 32)) to get a fixed-width big-endian encoding
- Strip any 0x hex prefix and validate the hex string length is 64 characters before decoding
Example fix
// before
var s p256OrdElement
_, err := s.SetBytes(scalarBytes) // may be wrong length
// after
if len(scalarBytes) != 32 {
return fmt.Errorf("scalar must be 32 bytes, got %d", len(scalarBytes))
}
fixed := make([]byte, 32)
scalarBigInt.FillBytes(fixed)
_, err := s.SetBytes(fixed) Defensive patterns
Strategy: validation
Validate before calling
func validateP256Scalar(b []byte) error {
if len(b) != 32 {
return fmt.Errorf("scalar must be exactly 32 bytes, got %d", len(b))
}
return nil
}
// Usage:
if err := validateP256Scalar(scalarBytes); err != nil { return err }
var s p256OrdElement
_, err := s.SetBytes(scalarBytes) Try / catch
_, err := s.SetBytes(x)
if err != nil {
return fmt.Errorf("invalid scalar: %w", err)
} Prevention
- Always use fixed 32-byte buffers for P-256 scalars
- Use big.Int.FillBytes(make([]byte, 32)) instead of big.Int.Bytes() to guarantee width
- Validate hex input is exactly 64 characters before decoding to bytes
When it happens
Trigger: Calling s.SetBytes(x) where len(x) != 32. This is a low-level scalar-field API used internally; it does not accept padded, truncated, or hex-encoded values.
Common situations: Passing a hex-decoded scalar without stripping the 0x prefix (yields 33 bytes), passing a DER/ASN.1-encoded integer, truncating a key share, or mixing up byte orders between little-endian and big-endian representations.
Related errors
- invalid scalar length
- invalid P256 element encoding
- invalid P256 point encoding
- invalid scalar length
- mlkem: invalid encapsulation key length
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/26b1de8df2bd59f6.
Report an issue: GitHub.