apache/pulsar · error · KeyManagementException
The private key algorithm is not supported. attempted: ${fai
Error message
The private key algorithm is not supported. attempted: ${failedAlgorithm} What it means
PemReader.loadPrivateKeyFromPemStream parses a PEM block and tries each KeyFactory algorithm in KEY_FACTORY_ALGORITHMS to build a PrivateKey from a PKCS8EncodedKeySpec. When every algorithm throws InvalidKeySpecException or NoSuchAlgorithmException, none could decode the key, so it throws KeyManagementException listing the attempted algorithms. This means the PEM content is not a decodable private key of any supported type.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/tls/PemReader.java:213
// Stop (and skip) at the last line that has, say, -----END [RSA] PRIVATE KEY-----
while ((currentLine = reader.readLine()) != null && !currentLine.startsWith("-----END")) {
sb.append(currentLine);
}
final KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(sb.toString()));
final List<String> failedAlgorithm = new ArrayList<>(KEY_FACTORY_ALGORITHMS.size());
for (String algorithm : KEY_FACTORY_ALGORITHMS) {
try {
KeyFactory keyFactory = jcaProvider != null ? KeyFactory.getInstance(algorithm, jcaProvider)
: KeyFactory.getInstance(algorithm);
PrivateKey key = keyFactory.generatePrivate(keySpec);
log.debug().attr("algorithm", algorithm).attr("provider", keyFactory.getProvider().getName())
.log("Loaded PEM private key");
return key;
} catch (InvalidKeySpecException | NoSuchAlgorithmException ex) {
failedAlgorithm.add(algorithm);
}
}
throw new KeyManagementException("The private key algorithm is not supported. attempted: "
+ StringUtils.join(failedAlgorithm, ","));
} catch (IOException e) {
throw new KeyManagementException("Private key loading error", e);
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Verify the file is an unencrypted PKCS#8 PEM ('-----BEGIN PRIVATE KEY-----'); re-export with: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8.pem
- Remove any passphrase protection (openssl rsa -in key.pem) or decrypt before loading; PemReader does not handle encrypted keys
- Check that the base64 body between BEGIN/END is intact (no truncation, whitespace corruption, or concatenated blocks)
- If passing a pinned jcaProvider, confirm it supports KeyFactory for the key's algorithm (RSA/EC/DSA), or pass null to use the JVM provider search
- Inspect the file content: ensure it is not a certificate ('BEGIN CERTIFICATE') or public key ('BEGIN PUBLIC KEY')
Example fix
// before (PKCS1 key rejected)
InputStream in = new FileInputStream("server-key.pem"); // -----BEGIN RSA PRIVATE KEY-----
PrivateKey key = PemReader.loadPrivateKeyFromPemFile("server-key.pem"); // throws
// after: convert to PKCS8 first
// $ openssl pkcs8 -topk8 -nocrypt -in server-key.pem -out server-key.pk8.pem
PrivateKey key = PemReader.loadPrivateKeyFromPemFile("server-key.pk8.pem"); // OK Defensive patterns
Strategy: try-catch
Validate before calling
// before calling PemReader
String pem = Files.readString(Path.of(keyPath));
if (!pem.contains("-----BEGIN")) throw new IllegalStateException("not a PEM file: " + keyPath);
if (pem.contains("ENCRYPTED")) throw new IllegalStateException("encrypted keys unsupported; decrypt first"); Type guard
static boolean looksLikePkcs8Pem(String pem) {
return pem != null && pem.contains("-----BEGIN PRIVATE KEY-----");
} Try / catch
try {
PrivateKey key = PemReader.loadPrivateKeyFromPemFile(keyPath);
} catch (KeyManagementException e) {
log.error("Cannot load TLS private key {}: {}", keyPath, e.getMessage());
throw new RuntimeException("Check key format (PKCS8, unencrypted) and provider support", e);
} Prevention
- Store keys as unencrypted PKCS#8 PEM ('BEGIN PRIVATE KEY'); convert with openssl pkcs8 -topk8 -nocrypt
- Verify the key loads once at startup (fail fast) rather than lazily at first TLS use
- Keep certificates and keys in separate, correctly named files
- Never reuse a consumed InputStream; open a fresh stream per load
- If using a pinned Provider, confirm it registers KeyFactory for RSA/EC
When it happens
Trigger: Calling PemReader.loadPrivateKeyFromPemFile/loadPrivateKeyFromPemStream with a PEM whose base64 body does not decode as PKCS8 under any supported KeyFactory algorithm (RSA, EC, etc.); a corrupted/truncated base64 body; an encrypted (password-protected) private key ('ENCRYPTED PRIVATE KEY' or 'BEGIN PRIVATE KEY' with Proc-Type headers that fail decode); a PKCS1 ('BEGIN RSA PRIVATE KEY') body in rare JVM/provider setups; a pinned jcaProvider that supplies none of the algorithms.
Common situations: Pointing broker/client TLS config at the wrong file (a certificate instead of a key, or a public key); an openssl-generated key still password-protected; a key in traditional PKCS1 format exported from older tooling; a FIPS or custom Provider lacking RSA/EC KeyFactory support; copy-paste mangling of the PEM body.
Related errors
- Failed to decode private key
- Unable to find EC Parameter for the given curve oid: ${ecOID
- ${logCtx}Failed to load public key ${keyName}. ${e.getMessag
- Cross-format TLS material: tlsPolicy(...) configures a keyst
- Cross-format TLS material: tlsPolicy(...) configures a PEM t
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/7404396b2e4dbdc1.
Report an issue: GitHub.