elastic/elasticsearch · error · SslConfigException
cannot read encrypted key [{}] without a password
Error message
cannot read encrypted key [{}] without a password What it means
Thrown by PemUtils.parsePrivateKey() when the file's first PEM header is `-----BEGIN ENCRYPTED PRIVATE KEY-----` (PKCS#8 encrypted) but the password supplier returned null. PKCS#8 encrypted keys cannot be decrypted without a password, so parsing aborts immediately.
Source
Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java:141
* encoded formats of encrypted and plaintext RSA, DSA and EC(secp256r1) keys
*
* @param keyPath the path for the key file
* @param passwordSupplier A password supplier for the potentially encrypted (password protected) key
* @return a private key from the contents of the file
*/
static PrivateKey parsePrivateKey(Path keyPath, Supplier<char[]> passwordSupplier) throws IOException, GeneralSecurityException {
try (BufferedReader bReader = Files.newBufferedReader(keyPath, StandardCharsets.UTF_8)) {
String line = bReader.readLine();
while (null != line && line.startsWith(HEADER) == false) {
line = bReader.readLine();
}
if (null == line) {
throw new SslConfigException("Error parsing Private Key [" + keyPath.toAbsolutePath() + "], file is empty");
}
if (PKCS8_ENCRYPTED_HEADER.equals(line.trim())) {
char[] password = passwordSupplier.get();
if (password == null) {
throw new SslConfigException("cannot read encrypted key [" + keyPath.toAbsolutePath() + "] without a password");
}
return parsePKCS8Encrypted(bReader, password);
} else if (PKCS8_HEADER.equals(line.trim())) {
return parsePKCS8(bReader);
} else if (PKCS1_HEADER.equals(line.trim())) {
return parsePKCS1Rsa(bReader, passwordSupplier);
} else if (OPENSSL_DSA_HEADER.equals(line.trim())) {
return parseOpenSslDsa(bReader, passwordSupplier);
} else if (OPENSSL_DSA_PARAMS_HEADER.equals(line.trim())) {
return parseOpenSslDsa(removeDsaHeaders(bReader), passwordSupplier);
} else if (OPENSSL_EC_HEADER.equals(line.trim())) {
return parseOpenSslEC(bReader, passwordSupplier);
} else if (OPENSSL_EC_PARAMS_HEADER.equals(line.trim())) {
return parseOpenSslEC(removeECHeaders(bReader), passwordSupplier);
} else {
throw new SslConfigException(
"cannot read PEM private key ["
+ keyPath.toAbsolutePath()View on GitHub (pinned to db6a809a66)
Solutions
- Add the key password to the Elasticsearch keystore: `bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password` (or the equivalent ssl.key_passphrase setting for PEM).
- If you do not need encryption, re-export the key unencrypted: `openssl pkcs8 -topk8 -in encrypted.pem -out plain.pem -nocrypt`.
- Verify the password setting name matches the SSL context (transport vs http) you are configuring.
- Confirm the password is non-empty and matches the one used to encrypt the key.
Example fix
# before: encrypted PKCS#8 key but no password configured # elasticsearch.yml xpack.security.http.ssl: enabled: true key: encrypted.pk8.pem certificate: cert.pem # after: add the passphrase via the keystore bin/elasticsearch-keystore add xpack.security.http.ssl.key.secure_password # (enter the password when prompted; restart Elasticsearch) # or re-export the key unencrypted: openssl pkcs8 -topk8 -in encrypted.pk8.pem -out plain.pk8.pem -nocrypt
Defensive patterns
Strategy: validation
Validate before calling
// Detect encrypted PKCS#8 keys and ensure a password is configured before parsing.
public static boolean isEncryptedPkcs8(Path p) throws IOException {
try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
String line;
while ((line = r.readLine()) != null) {
if (line.startsWith("-----BEGIN ENCRYPTED PRIVATE KEY-----")) return true;
if (line.startsWith("-----BEGIN")) return false;
}
}
return false;
}
// Configure Elasticsearch keystore:
// bin/elasticsearch-keystore add xpack.security.http.ssl.key.secure_password Prevention
- If the key starts with `-----BEGIN ENCRYPTED PRIVATE KEY-----`, a password is mandatory.
- Store the passphrase in the Elasticsearch keystore, not in plaintext elasticsearch.yml.
- If you cannot supply a password, re-export the key unencrypted (`openssl pkcs8 -nocrypt`).
When it happens
Trigger: parsePrivateKey detects PKCS8_ENCRYPTED_HEADER, calls passwordSupplier.get(), and the supplier returns null. Typical when Elasticsearch is configured with an encrypted PEM key but no `ssl.key_passphrase` / secure setting is provided, or when the keystore setting that should hold the passphrase is missing.
Common situations: Encrypted PKCS#8 key configured without a corresponding key password in elasticsearch.yml or the Elasticsearch keystore; password setting typo (`key_passphrase` vs `key_password`); password stored in a keystore entry that was not loaded; or the password supplier is wired to return null on missing config.
Related errors
- could not load ssl private key file [{}]
- Error parsing Private Key [{}], file is empty
- failed to load a KeyManager for certificate/key pair [{}], [
- cannot create trust using PEM certificates [{}]
- could not load ssl private key file [{}]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/8430c4af65440f16.
Report an issue: GitHub.