elastic/elasticsearch · error · SslConfigException

failed to load a KeyManager for certificate/key pair [{}], [

Error message

failed to load a KeyManager for certificate/key pair [{}], [{}]

What it means

Thrown by PemKeyConfig.createKeyManager() to wrap any GeneralSecurityException raised while building a KeyManager from a PEM certificate/key pair. The exception names the certificate path and key path so the operator can identify which configured pair failed.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemKeyConfig.java:95

            if (cert instanceof X509Certificate x509Certificate) {
                info.add(new StoredCertificate(x509Certificate, this.certificate, "PEM", null, first));
            }
            first = false;
        }
        return info;
    }

    @Override
    public X509ExtendedKeyManager createKeyManager() {
        final Path keyPath = resolve(key);
        final PrivateKey privateKey = getPrivateKey(keyPath);
        final Path certPath = resolve(this.certificate);
        final List<Certificate> certificates = getCertificates(certPath);
        try {
            final KeyStore keyStore = KeyStoreUtil.buildKeyStore(certificates, privateKey, keyPassword);
            return KeyStoreUtil.createKeyManager(keyStore, keyPassword, KeyManagerFactory.getDefaultAlgorithm());
        } catch (GeneralSecurityException e) {
            throw new SslConfigException("failed to load a KeyManager for certificate/key pair [" + certPath + "], [" + keyPath + "]", e);
        }
    }

    @Override
    public List<Tuple<PrivateKey, X509Certificate>> getKeys() {
        final Path keyPath = resolve(key);
        final Path certPath = resolve(this.certificate);
        final List<Certificate> certificates = getCertificates(certPath);
        if (certificates.isEmpty()) {
            return List.of();
        }
        final Certificate leafCertificate = certificates.get(0);
        if (leafCertificate instanceof X509Certificate x509Certificate) {
            return List.of(Tuple.tuple(getPrivateKey(keyPath), x509Certificate));
        } else {
            return List.of();
        }
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the key matches the certificate: `openssl x509 -in cert.pem -noout -modulus | openssl md5` equals `openssl rsa -in key.pem -noout -modulus | openssl md5` (RSA) or compare public keys for EC.
  2. Inspect the wrapped cause (SslConfigException.getCause()) for the specific security error.
  3. Re-export the key and certificate together from a CSR/CA workflow to guarantee they correspond.
  4. If the key is encrypted, ensure it uses a supported cipher (PKCS#5 PBES2 with AES, or legacy DES/DESede).

Example fix

# before: mismatched key/cert triggers wrapped exception
# elasticsearch.yml: xpack.security.http.ssl.certificate: cert.pem; key: wrong-key.pem

# after: verify match, then point both at the correct files
openssl x509 -in cert.pem -pubkey -noout | openssl md5
openssl pkey -in key.pem -pubout 2>/dev/null | openssl md5
# the two hashes must be equal
Defensive patterns

Strategy: validation

Validate before calling

// Verify key/cert correspondence BEFORE building the KeyManager.
public static void ensureKeyMatchesCert(PrivateKey key, X509Certificate cert) throws GeneralSecurityException {
    if (!key.getAlgorithm().equalsIgnoreCase(cert.getPublicKey().getAlgorithm())) {
        throw new GeneralSecurityException("key algorithm " + key.getAlgorithm() + " != cert " + cert.getPublicKey().getAlgorithm());
    }
    // For RSA/DSA/EC, compare encoded public keys.
    if (!Arrays.equals(key instanceof java.security.interfaces.RSAKey rk ? cert.getPublicKey().getEncoded() : cert.getPublicKey().getEncoded(), cert.getPublicKey().getEncoded())) {
        // simplified; in practice compare public-key encodings of derived vs cert
    }
}

Try / catch

try {
    return pemKeyConfig.createKeyManager();
} catch (SslConfigException e) {
    log.error("PEM key/cert pair failed; check modulus match and algorithm support: {}", e.getMessage(), e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: PemKeyConfig.createKeyManager() resolves key and certificate paths, calls PemUtils to parse them, then KeyStoreUtil.buildKeyStore(...) + KeyStoreUtil.createKeyManager(...). Any GeneralSecurityException (key/cert mismatch, unsupported algorithm, bad encoding, expired cert in chain) is wrapped here.

Common situations: Certificate and key do not match (modulus/public key differs), certificate chain is incomplete, key uses an algorithm unsupported by the JCE (e.g. Ed25519 on older JDKs), PEM file is malformed, or the key is encrypted with an unsupported PBES2 cipher (non-AES).

Understand the failure class

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/d7facb7b5589fcce. Report an issue: GitHub.