lcobucci/jwt · error · Lcobucci\JWT\Signer\InvalidKeyProvided
The type of the provided key is not
Error message
The type of the provided key is not "{expectedType}", "{actualType}" provided What it means
Ecdsa's guardAgainstIncompatibleKey verifies that the OpenSSL key material given to the signer is actually an EC key (OPENSSL_KEYTYPE_EC). If openssl_pkey_get_details() reports a different key type (RSA, DSA, Ed25519, DH), the signer throws InvalidKeyProvided::incompatibleKeyType naming the expected and actual key types. Each concrete ECDSA signer requires an EC key on its expected curve.
Solutions
- Generate a proper EC key on the required curve, e.g. openssl ecparam -name prime256v1 -genkey -noout -out ec-private.pem (use secp384r1 for ES384, secp521r1 for ES512).
- Inspect the loaded key with openssl_pkey_get_details(openssl_pkey_get_private($pem)) and confirm ['type'] === OPENSSL_KEYTYPE_EC before passing it to the signer.
- Point your configuration at the correct EC key file — the current path likely contains an RSA key.
- If migrating algorithms, re-sign tokens with the new EC key pair and update verifiers accordingly instead of reusing RSA keys.
Example fix
// before
$signer = new Es256();
$key = new Key(file_get_contents('rsa-private.pem')); // RSA key -> incompatibleKeyType
// after
shell_exec('openssl ecparam -name prime256v1 -genkey -noout -out ec-private.pem');
$key = new Key(file_get_contents('ec-private.pem')); // EC key on P-256 Defensive patterns
Strategy: validation
Validate before calling
$details = openssl_pkey_get_details(openssl_pkey_get_private($pem));
if (($details['type'] ?? null) !== OPENSSL_KEYTYPE_EC) {
throw new InvalidArgumentException('ECDSA signers require an EC key; got type ' . ($details['type'] ?? 'unknown'));
} Type guard
function isEcKeyString(string $pem): bool
{
$key = openssl_pkey_get_private($pem);
if ($key === false) {
return false;
}
return (openssl_pkey_get_details($key)['type'] ?? null) === OPENSSL_KEYTYPE_EC;
} Try / catch
try {
$token = $config->builder()->getToken($signer, $key);
} catch (InvalidKeyProvided $e) {
throw new ConfigurationException('Signing key incompatible with ECDSA signer: ' . $e->getMessage(), previous: $e);
} Prevention
- Keep EC and RSA key files in clearly separated directories and name files with the algorithm (ec-p256-private.pem).
- Validate key type at config load time with openssl_pkey_get_details before wiring a signer.
- When changing JWT algorithms, generate a brand-new key pair on the required curve rather than reusing RSA keys.
- Ensure openssl_pkey_get_private() succeeds (returns a key, not false) before using it — a failed parse can also surface as a wrong type.
When it happens
Trigger: Constructing an ECDSA signer (e.g. Es256, Es384, Es512) and calling sign/verify with a Key built from an RSA (or other) PEM/KEY string; passing an openssl key resource whose details['type'] !== OPENSSL_KEYTYPE_EC.
Common situations: Swapping signing algorithms (e.g. from RS256 to ES256) without regenerating the key pair; loading the wrong PEM file from disk; a config pointing at a shared RSA certificate; automated key rotation that injects a mismatched key.
Related errors
- The curve of the provided key is not
- The length of the provided key is different than
- The type of the provided key is not
- Key provided is shorter than
- Invalid signature length.
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/6d9bc89aabc2a203.
Report an issue: GitHub.
Appendix: source
Thrown at src/Signer/Ecdsa.php:39
$this->createSignature($key, $payload),
$this->pointLength(),
);
}
final public function verify(string $expected, string $payload, Key $key): bool
{
return $this->verifySignature(
$this->converter->toAsn1($expected, $this->pointLength()),
$payload,
$key,
);
}
/** {@inheritDoc} */
final protected function guardAgainstIncompatibleKey(int $type, int $lengthInBits): void
{
if ($type !== OPENSSL_KEYTYPE_EC) {
throw InvalidKeyProvided::incompatibleKeyType(
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) {View on GitHub (pinned to 375813049c)