{"record":{"id":"e0b22990ea8c92df","repo":"apereo/cas","slug":"could-not-decode-provided-keyfile","errorCode":null,"errorMessage":"Could not decode provided KeyFile ","messagePattern":"Could not decode provided KeyFile ","errorType":"exception","errorClass":"BeanCreationException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-saml-core-api/src/main/java/org/apereo/cas/support/saml/util/credential/BasicX509CredentialFactoryBean.java","lineNumber":157,"sourceCode":"        val certificates = new LazyList<X509Certificate>();\n        for (val r : certificateResources) {\n            try (val is = r.getInputStream()) {\n                certificates.addAll(X509Support.decodeCertificates(is));\n            } catch (final Exception e) {\n                throw new BeanCreationException(\"Could not decode provided CertificateFile: \" + r.getDescription(), e);\n            }\n        }\n        return certificates;\n    }\n\n    private PrivateKey getPrivateKey() {\n        if (null == privateKeyResource) {\n            return null;\n        }\n        try (val is = privateKeyResource.getInputStream()) {\n            return KeySupport.decodePrivateKey(is, getPrivateKeyPassword());\n        } catch (final Exception e) {\n            throw new BeanCreationException(\"Could not decode provided KeyFile \" + privateKeyResource.getDescription(), e);\n        }\n    }\n\n    @Override\n    public boolean isSingleton() {\n        return true;\n    }\n\n    private List<X509CRL> getCRLs() {\n        if (null == crlResources) {\n            return null;\n        }\n        val crls = new LazyList<X509CRL>();\n        for (val crl : crlResources) {\n            try (val is = crl.getInputStream()) {\n                crls.addAll(X509Support.decodeCRLs(is));\n            } catch (final Exception e) {\n                throw new BeanCreationException(\"Could not decode provided CRL file \" + crl.getDescription(), e);","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-saml-core-api/src/main/java/org/apereo/cas/support/saml/util/credential/BasicX509CredentialFactoryBean.java#L139-L175","documentation":"getPrivateKey() decodes the resource referenced by privateKeyResource into a PrivateKey using KeySupport.decodePrivateKey with the configured password. If the stream cannot be read or the key cannot be decoded (wrong format, wrong or missing password, unsupported algorithm), bean creation fails with BeanCreationException('Could not decode provided KeyFile <resource>', cause). This is the private-key analogue of the certificate decode errors.","triggerScenarios":"privateKeyResource is set, but its InputStream throws on read, or KeySupport.decodePrivateKey(is, getPrivateKeyPassword()) throws — e.g. PKCS#8 vs PKCS#1 mismatch, encrypted key with wrong or null password, garbage or truncated key file — inside getPrivateKey().","commonSituations":"Passing an encrypted PEM key without setting privateKeyPassword (or with the wrong one); providing a raw PKCS#1 'BEGIN RSA PRIVATE KEY' where PKCS#8 is expected; key file missing due to an unmounted volume or wrong path; pasting a public key or certificate into the key file; key truncated or corrupted during transfer.","solutions":["Verify the key file exists and is readable at the path in the message (ls -l; cat the header to confirm it is a PRIVATE KEY block).","If the key is encrypted, set the matching private-key-password property; if no password is intended, decrypt it: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key-pkcs8.pem.","Convert the key to PKCS#8 PEM, the most widely decodable form: openssl pkcs8 -topk8 -in idp_rsa.key -out idp_pkcs8.key.","Confirm the file actually contains a private key, not a certificate or public key; regenerate/export the key if truncated or corrupt."],"exampleFix":"# before: encrypted or PKCS#1 key with no password configured -> decode fails\ncas.authn.saml.idp.credential.private-key=file:/etc/cas/idp-encrypted.key\n# after: unencrypted PKCS#8 key (convert once with openssl pkcs8 -topk8 -nocrypt)\ncas.authn.saml.idp.credential.private-key=file:/etc/cas/idp-pkcs8.key","handlingStrategy":"validation","validationCode":"// pre-check the private key decodes with the configured password\ntry (var is = privateKeyResource.getInputStream()) {\n    KeySupport.decodePrivateKey(is, privateKeyPassword);\n} catch (Exception e) {\n    throw new IllegalStateException(\"Private key undecodable (format or password wrong): \" + privateKeyResource, e);\n}","typeGuard":null,"tryCatchPattern":"try {\n    credentialFactory.getObject();\n} catch (BeanCreationException e) {\n    if (e.getMessage().startsWith(\"Could not decode provided KeyFile\")) {\n        // cause is usually BadPaddingException/InvalidKeyException => wrong password/format\n        logger.error(\"Check private-key format (use PKCS#8) and privateKeyPassword\", e.getCause());\n    }\n    throw e;\n}","preventionTips":["Standardize on unencrypted PKCS#8 PEM (openssl pkcs8 -topk8) for private keys in CAS config.","If the key is encrypted, always set privateKeyPassword and manage it via environment variables/vault, not plaintext config.","Verify the file starts with '-----BEGIN PRIVATE KEY' (or 'ENCRYPTED PRIVATE KEY') not a certificate or public key.","Check permissions and existence of the key file in the container entrypoint before CAS starts."],"tags":["spring","saml","private-key","pkcs8","keystore"],"backgroundTag":"invalid-argument-format","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}