spring-projects/spring-security · error · Saml2Exception
Cannot encode certificate
Error message
Cannot encode certificate
What it means
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.
Source
Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/BaseOpenSamlMetadataResolver.java:173
private List<KeyDescriptor> buildKeys(Collection<Saml2X509Credential> credentials, UsageType usageType) {
List<KeyDescriptor> list = new ArrayList<>();
for (Saml2X509Credential credential : credentials) {
KeyDescriptor keyDescriptor = buildKeyDescriptor(usageType, credential.getCertificate());
list.add(keyDescriptor);
}
return list;
}
private KeyDescriptor buildKeyDescriptor(UsageType usageType, java.security.cert.X509Certificate certificate) {
KeyDescriptor keyDescriptor = this.saml.build(KeyDescriptor.DEFAULT_ELEMENT_NAME);
KeyInfo keyInfo = this.saml.build(KeyInfo.DEFAULT_ELEMENT_NAME);
X509Certificate x509Certificate = this.saml.build(X509Certificate.DEFAULT_ELEMENT_NAME);
X509Data x509Data = this.saml.build(X509Data.DEFAULT_ELEMENT_NAME);
try {
x509Certificate.setValue(new String(Base64.getEncoder().encode(certificate.getEncoded())));
}
catch (CertificateEncodingException ex) {
throw new Saml2Exception("Cannot encode certificate " + certificate.toString());
}
x509Data.getX509Certificates().add(x509Certificate);
keyInfo.getX509Datas().add(x509Data);
keyDescriptor.setUse(usageType);
keyDescriptor.setKeyInfo(keyInfo);
return keyDescriptor;
}
private AssertionConsumerService buildAssertionConsumerService(RelyingPartyRegistration registration) {
AssertionConsumerService assertionConsumerService = this.saml
.build(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
assertionConsumerService.setLocation(registration.getAssertionConsumerServiceLocation());
assertionConsumerService.setBinding(registration.getAssertionConsumerServiceBinding().getUrn());
assertionConsumerService.setIndex(1);
return assertionConsumerService;
}
private SingleLogoutService buildSingleLogoutService(RelyingPartyRegistration registration,View on GitHub (pinned to 96852e8860)
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
Example fix
// before
Certificate cert = // loaded from corrupt/truncated PEM
resolver.addSigningCert(cert);
// after
Certificate cert;
try (InputStream in = Files.newInputStream(Path.of("sp-signing.crt"))) {
cert = CertificateFactory.getInstance("X.509").generateCertificate(in);
}
resolver.addSigningCert(cert); Defensive patterns
Strategy: validation
Validate before calling
// verify cert encodes cleanly before building metadata
try {
byte[] der = certificate.getEncoded();
} catch (CertificateEncodingException e) {
throw new IllegalStateException("invalid signing certificate: re-export from PEM");
} Type guard
static boolean isEncodable(X509Certificate cert) {
try { cert.getEncoded(); return true; }
catch (CertificateEncodingException e) { return false; }
} Try / catch
try {
String metadata = resolver.generateMetadata(registration);
} catch (Saml2Exception e) {
if (e.getMessage() != null && e.getMessage().startsWith("Cannot encode certificate")) {
// replace corrupt credential with cleanly re-exported cert
}
} Prevention
- 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
When it happens
Trigger: keyDescriptor() -> buildKeyDescriptor(usageType, keyInfo, certificate) calls certificate.getEncoded(); a corrupt/unparseable X509Certificate object (failed internal re-encoding) throws CertificateEncodingException, wrapped as Saml2Exception.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Metadata response is missing verification certificates, nece
- Metadata response is missing a SingleSignOnService, necessar
- Unsupported element type:
- Unsupported element of type
- Failed to deserialize payload
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/790ccf3e19bb8e4a.
Report an issue: GitHub.