{"record":{"id":"6e76964be8f21a1e","repo":"golang/go","slug":"newpublickeyecdh-wrong-key-length","errorCode":null,"errorMessage":"NewPublicKeyECDH: wrong key length","messagePattern":"NewPublicKeyECDH: wrong key length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/boring/ecdh.go","lineNumber":38,"sourceCode":"\tbytes []byte\n}\n\nfunc (k *PublicKeyECDH) finalize() {\n\tC._goboringcrypto_EC_POINT_free(k.key)\n}\n\ntype PrivateKeyECDH struct {\n\tcurve string\n\tkey   *C.GO_EC_KEY\n}\n\nfunc (k *PrivateKeyECDH) finalize() {\n\tC._goboringcrypto_EC_KEY_free(k.key)\n}\n\nfunc NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) {\n\tif len(bytes) != 1+2*curveSize(curve) {\n\t\treturn nil, errors.New(\"NewPublicKeyECDH: wrong key length\")\n\t}\n\n\tnid, err := curveNID(curve)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tgroup := C._goboringcrypto_EC_GROUP_new_by_curve_name(nid)\n\tif group == nil {\n\t\treturn nil, fail(\"EC_GROUP_new_by_curve_name\")\n\t}\n\tdefer C._goboringcrypto_EC_GROUP_free(group)\n\tkey := C._goboringcrypto_EC_POINT_new(group)\n\tif key == nil {\n\t\treturn nil, fail(\"EC_POINT_new\")\n\t}\n\tok := C._goboringcrypto_EC_POINT_oct2point(group, key, (*C.uint8_t)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes)), nil) != 0\n\tif !ok {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/boring/ecdh.go#L20-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"Feeding a compressed point (33/49 bytes) where uncompressed is required; passing the wrong curve's encoding; truncation; confusing private and public key material.","solutions":["Provide the full uncompressed point (0x04 || X || Y) of the correct length for the curve.","Generate the encoding via ecdh.PublicKey.Bytes() on the standard library side rather than hand-encoding.","Match the curve string exactly to the key's actual curve."],"exampleFix":"// before\npub, err := boring.NewPublicKeyECDH(\"P-256\", compressed33Bytes) // 33 != 65\n\n// after\npub, err := boring.NewPublicKeyECDH(\"P-256\", uncompressed65Bytes) // 0x04||X||Y","handlingStrategy":"validation","validationCode":"func expectedEcdhPubLen(curve string) int {\n    switch curve {\n    case \"P-256\": return 65\n    case \"P-384\": return 97\n    case \"P-521\": return 133\n    }\n    return -1\n}\nfunc validateEcdhPub(curve string, b []byte) error {\n    if want := expectedEcdhPubLen(curve); want < 0 || len(b) != want {\n        return fmt.Errorf(\"expected %d bytes for %s public key, got %d\", want, curve, len(b))\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Encode public points via ecdh.PublicKey.Bytes() (uncompressed 0x04||X||Y).","Match the curve string to the key's actual curve.","Reject compressed encodings before calling the boring API."],"tags":["crypto","ecdh","boringcrypto","fips","validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}