golang/go · error
ecdsa: invalid private key length
Error message
ecdsa: invalid private key length
What it means
Thrown by fips140/ecdsa.NewPrivateKey when len(D) != c.N.Size(). D must be the fixed-length big-endian encoding of the private scalar with exactly the byte-width of the curve order (e.g. 32 for P-256, 48 for P-384, 66 for P-521). After this length check the scalar is parsed with SetBytes and additionally rejected if zero.
Source
Thrown at src/crypto/internal/fips140/ecdsa/ecdsa.go:170
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b,
0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09}
// NewPrivateKey creates a new ECDSA private key from the given D and Q byte
// slices. D must be the fixed-length big-endian encoding of the private scalar,
// and Q must be the compressed or uncompressed encoding of the public point.
func NewPrivateKey[P Point[P]](c *Curve[P], D, Q []byte) (*PrivateKey, error) {
fips140.RecordApproved()
pub, err := NewPublicKey(c, Q)
if err != nil {
return nil, err
}
if len(D) != c.N.Size() {
return nil, errors.New("ecdsa: invalid private key length")
}
d, err := bigmod.NewNat().SetBytes(D, c.N)
if err != nil {
return nil, err
}
if d.IsZero() == 1 {
return nil, errors.New("ecdsa: private key is zero")
}
priv := &PrivateKey{pub: *pub, d: d.Bytes(c.N)}
return priv, nil
}
// NewPublicKey creates a new ECDSA public key from the given Q byte slice.
// Q must be the compressed or uncompressed encoding of the public point.
func NewPublicKey[P Point[P]](c *Curve[P], Q []byte) (*PublicKey, error) {
// SetBytes checks that Q is a valid point on the curve, and that its
// coordinates are reduced modulo p, fulfilling the requirements of SP
// 800-89, Section 5.3.2.View on GitHub (pinned to b6b368adc5)
Solutions
- Left-pad (or trim) D to exactly c.N.Size() bytes in big-endian before calling NewPrivateKey.
- If D came from math/big, use the fixed-size FillBytes(buf) with a buffer of length c.N.Size() rather than Bytes().
- Verify the curve constant matches the key's intended curve.
Example fix
// before priv, err := ecdsa.NewPrivateKey(curve, bigInt.Bytes()) // variable length // after: fixed-width big-endian buf := make([]byte, curve.N.Size()) bigInt.FillBytes(buf) priv, err := ecdsa.NewPrivateKey(curve, buf)
Defensive patterns
Strategy: validation
Validate before calling
// Require exactly c.N.Size() bytes for the scalar.
if len(D) != curveN.Size() {
return fmt.Errorf("private scalar must be %d bytes", curveN.Size())
}
return ecdsa.NewPrivateKey(curve, D, Q) Type guard
func validScalarLen(D []byte, order *bigmod.Modulus) bool {
return len(D) == order.Size()
} Prevention
- Encode scalars with big.Int.FillBytes into a fixed-size buffer.
- Validate byte length against the curve order size at import.
- Do not strip leading zero bytes when serializing fixed-width fields.
When it happens
Trigger: Constructing an ECDSA private key whose D slice is shorter or longer than the curve order byte size, including a value with a stripped or extra leading byte.
Common situations: Importing a scalar encoded with a variable-length big.Int that dropped leading zeros or added a sign byte; cross-curve key reuse; truncated key material.
Related errors
- ecdsa: invalid public key encoding
- crypto/ecdh: invalid public key
- ecdsa: private key is zero
- ecdsa: private key does not match curve
- ecdsa: private key scalar is zero or negative
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/f04ad311266dad36.
Report an issue: GitHub.