{"record":{"id":"1f35f81764009173","repo":"BookStackApp/BookStack","slug":"key-loaded-from-file-path-is-not-an-rsa-key-as-exp","errorCode":null,"errorMessage":"Key loaded from file path is not an RSA key as expected","messagePattern":"Key loaded from file path is not an RSA key as expected","errorType":"exception","errorClass":"OidcInvalidKeyException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcJwtSigningKey.php","lineNumber":47,"sourceCode":"            throw new OidcInvalidKeyException('Unexpected type of key value provided');\n        }\n    }\n\n    /**\n     * @throws OidcInvalidKeyException\n     */\n    protected function loadFromPath(string $path): void\n    {\n        try {\n            $key = PublicKeyLoader::load(\n                file_get_contents($path)\n            );\n        } catch (\\Exception $exception) {\n            throw new OidcInvalidKeyException(\"Failed to load key from file path with error: {$exception->getMessage()}\");\n        }\n\n        if (!$key instanceof RSA) {\n            throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');\n        }\n\n        $this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);\n    }\n\n    /**\n     * @throws OidcInvalidKeyException\n     */\n    protected function loadFromJwkArray(array $jwk): void\n    {\n        // 'alg' is optional for a JWK, but we will still attempt to validate if\n        // it exists otherwise presume it will be compatible.\n        $alg = $jwk['alg'] ?? null;\n        if ($jwk['kty'] !== 'RSA' || !(is_null($alg) || $alg === 'RS256')) {\n            throw new OidcInvalidKeyException(\"Only RS256 keys are currently supported. Found key using {$alg}\");\n        }\n\n        // 'use' is optional for a JWK but we assume 'sig' where no value exists since that's what","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcJwtSigningKey.php#L29-L65","documentation":"After successfully loading the key file, loadFromPath verifies the result is an RSA key (phpseclib RSA instance) since only RS256/RSA signing is supported. A successfully parsed but non-RSA key (e.g. EC, Ed25519) triggers this exception.","triggerScenarios":"new OidcJwtSigningKey('file://...') where the file parses as a valid key but of a non-RSA type, such as an EC private key or Ed25519 key.","commonSituations":"IdP migrated to ES256 and the configured key is EC; developer points at an SSH ed25519 key by mistake; key generated with openssl ecparam instead of genrsa.","solutions":["Generate/use an RSA key: openssl genrsa -out key.pem 2048","If the IdP uses EC keys, switch the IdP to RS256 or obtain the RSA key/JWK","Check the jwks/discovery output — this class only supports RSA/RS256 keys","Re-export the key in RSA format if it was converted accidentally"],"exampleFix":"// before: EC key generated\nopenssl ecparam -name prime256v1 -genkey -out key.pem\n// after: RSA key\nopenssl genrsa -out key.pem 2048","handlingStrategy":"validation","validationCode":"$details = openssl_pkey_get_details(openssl_pkey_get_public(file_get_contents($path)));\nif (($details['type'] ?? null) !== OPENSSL_KEYTYPE_RSA) { throw new \\RuntimeException('key is not RSA'); }","typeGuard":null,"tryCatchPattern":"try { $key = new OidcJwtSigningKey('file://' . $path); } catch (OidcInvalidKeyException $e) { if (str_contains($e->getMessage(), 'not an RSA key')) { /* swap in an RSA key or switch IdP to RS256 */ } throw $e; }","preventionTips":["Generate keys with openssl genrsa (RSA only — this library does not support EC/Ed25519)","Keep IdP signing algorithm and local key type in sync (RS256)","Document key requirements wherever keys are provisioned"],"tags":["php","oidc","rsa","key-format"],"backgroundTag":"unsupported-key-type","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}