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

  1. Supply the raw fixed-length scalar (32/48/66 bytes for P-256/384/521).
  2. Obtain it via standard ecdh.PrivateKey.Bytes() (which returns the scalar).
  3. 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

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


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