golang/go · error
crypto/ecdh: invalid private key
Error message
crypto/ecdh: invalid private key
What it means
When BoringCrypto is enabled, NewPrivateKey delegates parsing to boring.NewPrivateKeyECDH(c.name, key). If that call fails, the key bytes are not a valid private scalar for the named NIST curve, so this generic 'invalid private key' error is returned. The second return path (bk.PublicKey()) is tracked separately at line 92.
Source
Thrown at src/crypto/ecdh/nist.go:88
bk, err := boring.NewPrivateKeyECDH(c.name, k.privateKey)
if err != nil {
return nil, err
}
pub, err := bk.PublicKey()
if err != nil {
return nil, err
}
k.boring = bk
k.publicKey.boring = pub
}
return k, nil
}
func (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error) {
if boring.Enabled {
bk, err := boring.NewPrivateKeyECDH(c.name, key)
if err != nil {
return nil, errors.New("crypto/ecdh: invalid private key")
}
pub, err := bk.PublicKey()
if err != nil {
return nil, errors.New("crypto/ecdh: invalid private key")
}
k := &PrivateKey{
curve: c,
privateKey: bytes.Clone(key),
publicKey: &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub},
boring: bk,
}
return k, nil
}
fk, err := c.newPrivateKey(key)
if err != nil {
return nil, err
}View on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the key bytes are the raw, fixed-length scalar for the exact curve used.
- Generate keys via curve.GenerateKey(rand.Reader) so encoding is always valid.
- Verify key length matches the curve's expected private-key size before calling NewPrivateKey.
Defensive patterns
Strategy: validation
Validate before calling
// Validate length/range for the NIST curve before NewPrivateKey.
// P-256 expects 32 bytes, P-384 48, P-521 66.
func loadPriv(curve ecdh.Curve, key []byte) (*ecdh.PrivateKey, error) {
if len(key) == 0 {
return nil, errors.New("empty private key")
}
return curve.NewPrivateKey(key)
} Try / catch
priv, err := curve.NewPrivateKey(key)
if err != nil {
// 'invalid private key' under BoringCrypto: reject and request a fresh key.
return err
} Prevention
- Obtain private keys from curve.GenerateKey(rand.Reader), not from external byte sources.
- When loading persisted keys, verify byte length matches the curve's scalar size.
- Discard keys that fail to construct; never try to patch the bytes.
When it happens
Trigger: Calling curve.NewPrivateKey(key) with malformed, out-of-range, or wrong-length scalar bytes while boring.Enabled is true.
Common situations: Loading a key with the wrong curve's encoding; truncated key bytes; a scalar that is zero or >= the curve order; key produced by a non-compatible library.
Related errors
- crypto/ecdh: private key and public key curves do not match
- crypto/ecdh: invalid public key
- crypto/dsa: invalid public key
- point not on curve
- crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/a40d6db320d7d466.
Report an issue: GitHub.