{"record":{"id":"a40d6db320d7d466","repo":"golang/go","slug":"crypto-ecdh-invalid-private-key","errorCode":null,"errorMessage":"crypto/ecdh: invalid private key","messagePattern":"crypto/ecdh: invalid private key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/ecdh/nist.go","lineNumber":88,"sourceCode":"\t\tbk, err := boring.NewPrivateKeyECDH(c.name, k.privateKey)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpub, err := bk.PublicKey()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tk.boring = bk\n\t\tk.publicKey.boring = pub\n\t}\n\treturn k, nil\n}\n\nfunc (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error) {\n\tif boring.Enabled {\n\t\tbk, err := boring.NewPrivateKeyECDH(c.name, key)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"crypto/ecdh: invalid private key\")\n\t\t}\n\t\tpub, err := bk.PublicKey()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"crypto/ecdh: invalid private key\")\n\t\t}\n\t\tk := &PrivateKey{\n\t\t\tcurve:      c,\n\t\t\tprivateKey: bytes.Clone(key),\n\t\t\tpublicKey:  &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub},\n\t\t\tboring:     bk,\n\t\t}\n\t\treturn k, nil\n\t}\n\n\tfk, err := c.newPrivateKey(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/ecdh/nist.go#L70-L106","documentation":"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.","triggerScenarios":"Calling curve.NewPrivateKey(key) with malformed, out-of-range, or wrong-length scalar bytes while boring.Enabled is true.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate length/range for the NIST curve before NewPrivateKey.\n// P-256 expects 32 bytes, P-384 48, P-521 66.\nfunc loadPriv(curve ecdh.Curve, key []byte) (*ecdh.PrivateKey, error) {\n    if len(key) == 0 {\n        return nil, errors.New(\"empty private key\")\n    }\n    return curve.NewPrivateKey(key)\n}","typeGuard":null,"tryCatchPattern":"priv, err := curve.NewPrivateKey(key)\nif err != nil {\n    // 'invalid private key' under BoringCrypto: reject and request a fresh key.\n    return err\n}","preventionTips":["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."],"tags":["crypto","ecdh","keys","boringcrypto","validation","go","security"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}