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

  1. Replace the configured certificate with one re-exported from a valid PEM/DER source (openssl x509, keytool -exportcert)
  2. Verify the credential loads cleanly: CertificateFactory.getInstance("X.509").generateCertificate(in) without error
  3. Check the keystore entry isn't corrupt; re-import the cert and restart
  4. 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

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.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/790ccf3e19bb8e4a. Report an issue: GitHub.