{"record":{"id":"52a5dfe24fe46596","repo":"lcobucci/jwt","slug":"the-curve-of-the-provided-key-is-not-expectedcurve","errorCode":null,"errorMessage":"The curve of the provided key is not \"{expectedCurve}\", \"{actualCurve}\" provided","messagePattern":"The curve of the provided key is not \"(.+?)\", \"(.+?)\" provided","errorType":"exception","errorClass":"Lcobucci\\JWT\\Signer\\InvalidKeyProvided","httpStatus":null,"severity":"error","filePath":"src/Signer/Ecdsa.php","lineNumber":58,"sourceCode":"                self::KEY_TYPE_MAP[OPENSSL_KEYTYPE_EC],\n                self::KEY_TYPE_MAP[$type] ?? 'unknown',\n            );\n        }\n\n        $expectedKeyLength = $this->expectedKeyLength();\n\n        if ($lengthInBits !== $expectedKeyLength) {\n            throw InvalidKeyProvided::incompatibleKeyLength($expectedKeyLength, $lengthInBits);\n        }\n    }\n\n    /** {@inheritDoc} */\n    final protected function guardAgainstIncompatibleCurve(?string $curveName): void\n    {\n        $expectedCurve = $this->expectedCurve();\n\n        if ($curveName !== $expectedCurve) {\n            throw InvalidKeyProvided::incompatibleKeyCurve($expectedCurve, $curveName ?? 'unknown');\n        }\n    }\n\n    /**\n     * @internal\n     *\n     * @return positive-int\n     */\n    abstract public function expectedKeyLength(): int;\n\n    /**\n     * Returns the name of the curve that keys must use\n     *\n     * @internal\n     */\n    abstract public function expectedCurve(): string;\n\n    /**","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Signer/Ecdsa.php#L40-L76","documentation":"Ecdsa's guardAgainstIncompatibleCurve compares the curve name reported by openssl_pkey_get_details() (details['ec']['curve_name']) with the curve required by the concrete signer via expectedCurve(). If they differ (or the curve is unknown/null), it throws InvalidKeyProvided::incompatibleKeyCurve with the expected and actual curve names. This ensures tokens are signed on exactly the curve the algorithm mandates.","triggerScenarios":"Calling sign()/verify() with an EC key generated on the wrong named curve — e.g. an Ed25519 or secp256k1 key passed to Es256, or a P-384 key passed to Es256 — so details['ec']['curve_name'] !== expectedCurve().","commonSituations":"openssl ecparam defaulting to a different curve than expected; reusing keys across signers with different curves; keys generated by cloud KMS/HSMs on non-standard curves; null curve_name when OpenSSL cannot resolve the curve (rare).","solutions":["Generate the key on the exact required curve: openssl ecparam -name prime256v1 -genkey (P-256), secp384r1 (P-384), secp521r1 (P-521).","Print the current curve: openssl_pkey_get_details(openssl_pkey_get_private($pem))['ec']['curve_name'] to see what you actually have.","Use the signer class that matches the key's curve instead of the one you instantiated (e.g. Es384 for a secp384r1 key).","When keys come from a KMS/HSM, request/export them explicitly on the standard curve the algorithm requires."],"exampleFix":"// before\n$signer = new Es256();\n$key = new Key(file_get_contents('secp256k1-key.pem')); // wrong curve -> incompatibleKeyCurve\n\n// after\nshell_exec('openssl ecparam -name prime256v1 -genkey -noout -out p256-key.pem');\n$signer = new Es256();\n$key = new Key(file_get_contents('p256-key.pem')); // prime256v1","handlingStrategy":"validation","validationCode":"$details = openssl_pkey_get_details(openssl_pkey_get_private($pem));\n$curve = $details['ec']['curve_name'] ?? null;\nif ($curve !== 'prime256v1') { // expected curve of the signer, e.g. Es256\n    throw new InvalidArgumentException('EC key curve is ' . ($curve ?? 'unknown') . '; expected prime256v1');\n}","typeGuard":"function isOnCurve(string $pem, string $expectedCurve): bool\n{\n    $key = openssl_pkey_get_private($pem);\n    $details = $key === false ? null : openssl_pkey_get_details($key);\n    return ($details['ec']['curve_name'] ?? null) === $expectedCurve;\n}","tryCatchPattern":"try {\n    $token = $config->builder()->getToken($signer, $key);\n} catch (InvalidKeyProvided $e) {\n    throw new ConfigurationException('ECDSA key curve mismatch: ' . $e->getMessage(), previous: $e);\n}","preventionTips":["Always pass an explicit -name to openssl ecparam when generating EC keys; never rely on defaults.","Verify curve_name with openssl_pkey_get_details (or `openssl ec -text -noout`) before deploying a key.","Standardize curve choice per algorithm in your key-management docs and rotation scripts.","When importing keys from HSM/KMS providers, confirm the exported curve matches the JOSE algorithm's requirement."],"tags":["ecdsa","curve","openssl","signing"],"backgroundTag":"invalid-key-curve","analyzedSha":"375813049c24c7111bda8b6884c57b071ceb2fe7","analyzedAt":"2026-09-14T11:12:28.004Z","contentChangedAt":"2026-09-14T11:12:28.004Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}