{"record":{"id":"68788e993c14964f","repo":"slackhq/nebula","slug":"cannot-parse-private-key-as-p256-w","errorCode":null,"errorMessage":"cannot parse private key as P256: %w","messagePattern":"cannot parse private key as P256: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/cert_v1.go","lineNumber":153,"sourceCode":"func (c *certificateV1) VerifyPrivateKey(curve Curve, key []byte) error {\n\tif curve != c.details.curve {\n\t\treturn fmt.Errorf(\"curve in cert and private key supplied don't match\")\n\t}\n\tif c.details.isCA {\n\t\tswitch curve {\n\t\tcase Curve_CURVE25519:\n\t\t\t// the call to PublicKey below will panic slice bounds out of range otherwise\n\t\t\tif len(key) != ed25519.PrivateKeySize {\n\t\t\t\treturn fmt.Errorf(\"key was not 64 bytes, is invalid ed25519 private key\")\n\t\t\t}\n\n\t\t\tif !ed25519.PublicKey(c.details.publicKey).Equal(ed25519.PrivateKey(key).Public()) {\n\t\t\t\treturn fmt.Errorf(\"public key in cert and private key supplied don't match\")\n\t\t\t}\n\t\tcase Curve_P256:\n\t\t\tprivkey, err := ecdh.P256().NewPrivateKey(key)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot parse private key as P256: %w\", err)\n\t\t\t}\n\t\t\tpub := privkey.PublicKey().Bytes()\n\t\t\tif !bytes.Equal(pub, c.details.publicKey) {\n\t\t\t\treturn fmt.Errorf(\"public key in cert and private key supplied don't match\")\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid curve: %s\", curve)\n\t\t}\n\t\treturn nil\n\t}\n\n\tvar pub []byte\n\tswitch curve {\n\tcase Curve_CURVE25519:\n\t\tvar err error\n\t\tpub, err = curve25519.X25519(key, curve25519.Basepoint)\n\t\tif err != nil {\n\t\t\treturn err","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/cert_v1.go#L135-L171","documentation":"VerifyPrivateKey's P256 branch parses the raw private key bytes with crypto/ecdh's P256 NewPrivateKey before deriving the public key. If the bytes are not a valid scalar in the P256 field (wrong length, leading issues, not a real key), the parse fails and this error wraps the underlying reason.","triggerScenarios":"Calling (*certificateV1).VerifyPrivateKey with curve=Curve_P256 and key bytes that ecdh.P256().NewPrivateKey rejects (wrong size, all-zero, out of range, or actually an Ed25519 key).","commonSituations":"Passing an Ed25519 64-byte private key to a P256 certificate; key file contains PEM text not stripped to raw bytes; truncated or corrupted key file; NIST-curve vs Ed25519 confusion in config.","solutions":["Confirm the certificate's curve matches the key's curve and pass the correct curve constant","Strip PEM armor and decode base64 so only the raw key bytes are passed","Re-issue the keypair/certificate for the intended curve if the key was generated for a different curve","Inspect the wrapped error (%w) to see the exact ecdh parse failure"],"exampleFix":"// before\ncert.VerifyPrivateKey(key, cert.Curve_P256, ed25519KeyBytes) // cannot parse as P256\n// after\np256Key := generateP256KeyRaw() // raw 32-byte P256 scalar\ncert.VerifyPrivateKey(key, cert.Curve_P256, p256Key)","handlingStrategy":"validation","validationCode":"func isRawP256Key(b []byte) bool {\n    _, err := ecdh.P256().NewPrivateKey(b)\n    return err == nil\n}\nif !isRawP256Key(keyBytes) {\n    return fmt.Errorf(\"key bytes are not a valid P256 private key\")\n}\nerr := c.VerifyPrivateKey(key, cert.Curve_P256, keyBytes)","typeGuard":"func isP256Sized(b []byte) bool { return len(b) == 32 }","tryCatchPattern":"if err := c.VerifyPrivateKey(key, cert.Curve_P256, keyBytes); err != nil {\n    if strings.Contains(err.Error(), \"cannot parse private key as P256\") {\n        return fmt.Errorf(\"supplied key is not a valid P256 scalar: %w\", err)\n    }\n    return err\n}","preventionTips":["Match the curve when generating keys and certificates","Strip PEM/base64 to raw bytes before passing the key","Store keys in a fixed raw binary format to avoid format drift","Log the wrapped cause of ecdh parse failures to diagnose quickly"],"tags":["certificate","p256","ecdh","key-format"],"backgroundTag":"invalid-private-key","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}