lcobucci/jwt · error · Lcobucci\JWT\Signer\InvalidKeyProvided
The curve of the provided key is not
Error message
The curve of the provided key is not "{expectedCurve}", "{actualCurve}" provided What it means
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.
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.
Example fix
// before
$signer = new Es256();
$key = new Key(file_get_contents('secp256k1-key.pem')); // wrong curve -> incompatibleKeyCurve
// after
shell_exec('openssl ecparam -name prime256v1 -genkey -noout -out p256-key.pem');
$signer = new Es256();
$key = new Key(file_get_contents('p256-key.pem')); // prime256v1 Defensive patterns
Strategy: validation
Validate before calling
$details = openssl_pkey_get_details(openssl_pkey_get_private($pem));
$curve = $details['ec']['curve_name'] ?? null;
if ($curve !== 'prime256v1') { // expected curve of the signer, e.g. Es256
throw new InvalidArgumentException('EC key curve is ' . ($curve ?? 'unknown') . '; expected prime256v1');
} Type guard
function isOnCurve(string $pem, string $expectedCurve): bool
{
$key = openssl_pkey_get_private($pem);
$details = $key === false ? null : openssl_pkey_get_details($key);
return ($details['ec']['curve_name'] ?? null) === $expectedCurve;
} Try / catch
try {
$token = $config->builder()->getToken($signer, $key);
} catch (InvalidKeyProvided $e) {
throw new ConfigurationException('ECDSA key curve mismatch: ' . $e->getMessage(), previous: $e);
} Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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).
Related errors
- The type of the provided key is not
- The length of the provided key is different than
- Key provided is shorter than
- Invalid signature length.
- Invalid data. Should start with a sequence.
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/52a5dfe24fe46596.
Report an issue: GitHub.
Appendix: source
Thrown at src/Signer/Ecdsa.php:58
self::KEY_TYPE_MAP[OPENSSL_KEYTYPE_EC],
self::KEY_TYPE_MAP[$type] ?? 'unknown',
);
}
$expectedKeyLength = $this->expectedKeyLength();
if ($lengthInBits !== $expectedKeyLength) {
throw InvalidKeyProvided::incompatibleKeyLength($expectedKeyLength, $lengthInBits);
}
}
/** {@inheritDoc} */
final protected function guardAgainstIncompatibleCurve(?string $curveName): void
{
$expectedCurve = $this->expectedCurve();
if ($curveName !== $expectedCurve) {
throw InvalidKeyProvided::incompatibleKeyCurve($expectedCurve, $curveName ?? 'unknown');
}
}
/**
* @internal
*
* @return positive-int
*/
abstract public function expectedKeyLength(): int;
/**
* Returns the name of the curve that keys must use
*
* @internal
*/
abstract public function expectedCurve(): string;
/**View on GitHub (pinned to 375813049c)