golang/go · error
NewPrivateKeyECDH: wrong key length
Error message
NewPrivateKeyECDH: wrong key length
What it means
Raised by boring.NewPrivateKeyECDH when the supplied scalar bytes are not exactly curveSize(curve) bytes — the byte length of a single curve coordinate/scalar. P-256: 32 bytes, P-384: 48, P-521: 66.
Source
Thrown at src/crypto/internal/boring/ecdh.go:74
if !ok {
C._goboringcrypto_EC_POINT_free(key)
return nil, errors.New("point not on curve")
}
k := &PublicKeyECDH{curve, key, append([]byte(nil), bytes...)}
// Note: Because of the finalizer, any time k.key is passed to cgo,
// that call must be followed by a call to runtime.KeepAlive(k),
// to make sure k is not collected (and finalized) before the cgo
// call returns.
runtime.SetFinalizer(k, (*PublicKeyECDH).finalize)
return k, nil
}
func (k *PublicKeyECDH) Bytes() []byte { return k.bytes }
func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) {
if len(bytes) != curveSize(curve) {
return nil, errors.New("NewPrivateKeyECDH: wrong key length")
}
nid, err := curveNID(curve)
if err != nil {
return nil, err
}
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
if key == nil {
return nil, fail("EC_KEY_new_by_curve_name")
}
b := bytesToBN(bytes)
ok := b != nil && C._goboringcrypto_EC_KEY_set_private_key(key, b) != 0
if b != nil {
C._goboringcrypto_BN_free(b)
}
if !ok {
C._goboringcrypto_EC_KEY_free(key)
return nil, fail("EC_KEY_set_private_key")View on GitHub (pinned to b6b368adc5)
Solutions
- Supply the raw fixed-length scalar (32/48/66 bytes for P-256/384/521).
- Obtain it via standard ecdh.PrivateKey.Bytes() (which returns the scalar).
- Match the curve string to the scalar's actual curve.
Example fix
// before
priv, err := boring.NewPrivateKeyECDH("P-256", pubPoint65Bytes) // 65 != 32
// after
priv, err := boring.NewPrivateKeyECDH("P-256", scalar32Bytes) Defensive patterns
Strategy: validation
Validate before calling
func expectedEcdhScalarLen(curve string) int {
switch curve {
case "P-256": return 32
case "P-384": return 48
case "P-521": return 66
}
return -1
}
func validateEcdhPriv(curve string, b []byte) error {
if want := expectedEcdhScalarLen(curve); want < 0 || len(b) != want {
return fmt.Errorf("expected %d-byte scalar for %s, got %d", want, curve, len(b))
}
return nil
} Prevention
- Obtain scalars via ecdh.PrivateKey.Bytes().
- Do not pass a public point where a private scalar is expected.
- Match the curve string to the scalar's curve.
When it happens
Trigger: Calling NewPrivateKeyECDH(curve, bytes) with len(bytes) != curveSize(curve): wrong-size scalar, a public point passed instead of a private scalar, or bytes from a different curve.
Common situations: Passing the uncompressed public point (65 bytes) where the 32-byte scalar is expected; mixing curve scalar sizes; truncated or padded scalars; DER/PEM-encoded keys not decoded first.
Related errors
- NewPublicKeyECDH: wrong key length
- point not on curve
- boringcrypto: unknown elliptic curve
- crypto/ecdh: invalid private key
- crypto/aes: GCM tag and nonce sizes can't be non-standard at
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/2eb15cc991bcbe0a.
Report an issue: GitHub.