golang/go · error

NewPublicKeyECDH: wrong key length

Error message

NewPublicKeyECDH: wrong key length

What it means

Raised by boring.NewPublicKeyECDH when the supplied bytes are not the expected length for an uncompressed ECDH public point on the given curve: 1 + 2*curveSize bytes (a 0x04 prefix plus X and Y). For P-256 that is 65 bytes, P-384 97, P-521 133.

Source

Thrown at src/crypto/internal/boring/ecdh.go:38

	bytes []byte
}

func (k *PublicKeyECDH) finalize() {
	C._goboringcrypto_EC_POINT_free(k.key)
}

type PrivateKeyECDH struct {
	curve string
	key   *C.GO_EC_KEY
}

func (k *PrivateKeyECDH) finalize() {
	C._goboringcrypto_EC_KEY_free(k.key)
}

func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) {
	if len(bytes) != 1+2*curveSize(curve) {
		return nil, errors.New("NewPublicKeyECDH: wrong key length")
	}

	nid, err := curveNID(curve)
	if err != nil {
		return nil, err
	}

	group := C._goboringcrypto_EC_GROUP_new_by_curve_name(nid)
	if group == nil {
		return nil, fail("EC_GROUP_new_by_curve_name")
	}
	defer C._goboringcrypto_EC_GROUP_free(group)
	key := C._goboringcrypto_EC_POINT_new(group)
	if key == nil {
		return nil, fail("EC_POINT_new")
	}
	ok := C._goboringcrypto_EC_POINT_oct2point(group, key, (*C.uint8_t)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes)), nil) != 0
	if !ok {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Provide the full uncompressed point (0x04 || X || Y) of the correct length for the curve.
  2. Generate the encoding via ecdh.PublicKey.Bytes() on the standard library side rather than hand-encoding.
  3. Match the curve string exactly to the key's actual curve.

Example fix

// before
pub, err := boring.NewPublicKeyECDH("P-256", compressed33Bytes) // 33 != 65

// after
pub, err := boring.NewPublicKeyECDH("P-256", uncompressed65Bytes) // 0x04||X||Y
Defensive patterns

Strategy: validation

Validate before calling

func expectedEcdhPubLen(curve string) int {
    switch curve {
    case "P-256": return 65
    case "P-384": return 97
    case "P-521": return 133
    }
    return -1
}
func validateEcdhPub(curve string, b []byte) error {
    if want := expectedEcdhPubLen(curve); want < 0 || len(b) != want {
        return fmt.Errorf("expected %d bytes for %s public key, got %d", want, curve, len(b))
    }
    return nil
}

Prevention

When it happens

Trigger: Calling NewPublicKeyECDH(curve, bytes) with len(bytes) != 1 + 2*curveSize(curve). Caused by passing a compressed point, a private key scalar, raw X-only bytes, or bytes encoded for a different curve.

Common situations: Feeding a compressed point (33/49 bytes) where uncompressed is required; passing the wrong curve's encoding; truncation; confusing private and public key material.

Related errors


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