{"record":{"id":"790ccf3e19bb8e4a","repo":"spring-projects/spring-security","slug":"cannot-encode-certificate","errorCode":null,"errorMessage":"Cannot encode certificate ","messagePattern":"Cannot encode certificate ","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/BaseOpenSamlMetadataResolver.java","lineNumber":173,"sourceCode":"\tprivate List<KeyDescriptor> buildKeys(Collection<Saml2X509Credential> credentials, UsageType usageType) {\n\t\tList<KeyDescriptor> list = new ArrayList<>();\n\t\tfor (Saml2X509Credential credential : credentials) {\n\t\t\tKeyDescriptor keyDescriptor = buildKeyDescriptor(usageType, credential.getCertificate());\n\t\t\tlist.add(keyDescriptor);\n\t\t}\n\t\treturn list;\n\t}\n\n\tprivate KeyDescriptor buildKeyDescriptor(UsageType usageType, java.security.cert.X509Certificate certificate) {\n\t\tKeyDescriptor keyDescriptor = this.saml.build(KeyDescriptor.DEFAULT_ELEMENT_NAME);\n\t\tKeyInfo keyInfo = this.saml.build(KeyInfo.DEFAULT_ELEMENT_NAME);\n\t\tX509Certificate x509Certificate = this.saml.build(X509Certificate.DEFAULT_ELEMENT_NAME);\n\t\tX509Data x509Data = this.saml.build(X509Data.DEFAULT_ELEMENT_NAME);\n\t\ttry {\n\t\t\tx509Certificate.setValue(new String(Base64.getEncoder().encode(certificate.getEncoded())));\n\t\t}\n\t\tcatch (CertificateEncodingException ex) {\n\t\t\tthrow new Saml2Exception(\"Cannot encode certificate \" + certificate.toString());\n\t\t}\n\t\tx509Data.getX509Certificates().add(x509Certificate);\n\t\tkeyInfo.getX509Datas().add(x509Data);\n\t\tkeyDescriptor.setUse(usageType);\n\t\tkeyDescriptor.setKeyInfo(keyInfo);\n\t\treturn keyDescriptor;\n\t}\n\n\tprivate AssertionConsumerService buildAssertionConsumerService(RelyingPartyRegistration registration) {\n\t\tAssertionConsumerService assertionConsumerService = this.saml\n\t\t\t.build(AssertionConsumerService.DEFAULT_ELEMENT_NAME);\n\t\tassertionConsumerService.setLocation(registration.getAssertionConsumerServiceLocation());\n\t\tassertionConsumerService.setBinding(registration.getAssertionConsumerServiceBinding().getUrn());\n\t\tassertionConsumerService.setIndex(1);\n\t\treturn assertionConsumerService;\n\t}\n\n\tprivate SingleLogoutService buildSingleLogoutService(RelyingPartyRegistration registration,","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/BaseOpenSamlMetadataResolver.java#L155-L191","documentation":"BaseOpenSamlMetadataResolver.buildKeyDescriptor builds an X509Certificate element for SP metadata by Base64-encoding certificate.getEncoded(). If the certificate cannot be encoded (CertificateEncodingException), a Saml2Exception \"Cannot encode certificate \" + certificate is thrown, aborting metadata generation.","triggerScenarios":"keyDescriptor() -> buildKeyDescriptor(usageType, keyInfo, certificate) calls certificate.getEncoded(); a corrupt/unparseable X509Certificate object (failed internal re-encoding) throws CertificateEncodingException, wrapped as Saml2Exception.","commonSituations":"A signing/encryption certificate loaded from a malformed PEM/DER file, keystore, or classpath resource that cannot be re-encoded to DER; certificate objects constructed via unusual providers or manually assembled bytes.","solutions":["Replace the configured certificate with one re-exported from a valid PEM/DER source (openssl x509, keytool -exportcert)","Verify the credential loads cleanly: CertificateFactory.getInstance(\"X.509\").generateCertificate(in) without error","Check the keystore entry isn't corrupt; re-import the cert and restart","Log certificate.getSubjectDN()/getNotBefore/notAfter to confirm the loaded cert is the intended one"],"exampleFix":"// before\n Certificate cert = // loaded from corrupt/truncated PEM\n resolver.addSigningCert(cert);\n// after\n Certificate cert;\n try (InputStream in = Files.newInputStream(Path.of(\"sp-signing.crt\"))) {\n     cert = CertificateFactory.getInstance(\"X.509\").generateCertificate(in);\n }\n resolver.addSigningCert(cert);","handlingStrategy":"validation","validationCode":"// verify cert encodes cleanly before building metadata\ntry {\n    byte[] der = certificate.getEncoded();\n} catch (CertificateEncodingException e) {\n    throw new IllegalStateException(\"invalid signing certificate: re-export from PEM\");\n}","typeGuard":"static boolean isEncodable(X509Certificate cert) {\n    try { cert.getEncoded(); return true; }\n    catch (CertificateEncodingException e) { return false; }\n}","tryCatchPattern":"try {\n    String metadata = resolver.generateMetadata(registration);\n} catch (Saml2Exception e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Cannot encode certificate\")) {\n        // replace corrupt credential with cleanly re-exported cert\n    }\n}","preventionTips":["Load certificates via CertificateFactory from valid PEM/DER files","Validate all configured certs at startup, not at metadata generation","Re-export certs with openssl/keytool if loaded from unusual sources","Verify keystore integrity after any certificate rotation"],"tags":["saml2","metadata","certificate","x509"],"backgroundTag":"invalid-argument-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}