elastic/elasticsearch · error · IOException

Malformed PEM file, EC Key header is missing

Error message

Malformed PEM file, EC Key header is missing

What it means

Thrown by removeECHeaders immediately after the EC PARAMETERS footer has been located. It reads the next line and expects it to be '-----BEGIN EC PRIVATE KEY-----'; if it is null (EOF) or any other value, the PEM structure is broken. This protects parseOpenSslEC from receiving a reader positioned at the wrong place.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java:185

     * Removes the EC Headers that OpenSSL adds to EC private keys as the information in them
     * is redundant
     *
     * @throws IOException if the EC Parameter footer is missing
     */
    private static BufferedReader removeECHeaders(BufferedReader bReader) throws IOException {
        String line = bReader.readLine();
        while (line != null) {
            if (OPENSSL_EC_PARAMS_FOOTER.equals(line.trim())) {
                break;
            }
            line = bReader.readLine();
        }
        if (null == line || OPENSSL_EC_PARAMS_FOOTER.equals(line.trim()) == false) {
            throw new IOException("Malformed PEM file, EC Parameters footer is missing");
        }
        // Verify that the key starts with the correct header before passing it to parseOpenSslEC
        if (OPENSSL_EC_HEADER.equals(bReader.readLine()) == false) {
            throw new IOException("Malformed PEM file, EC Key header is missing");
        }
        return bReader;
    }

    /**
     * Removes the DSA Params Headers that OpenSSL adds to DSA private keys as the information in them
     * is redundant
     *
     * @throws IOException if the EC Parameter footer is missing
     */
    private static BufferedReader removeDsaHeaders(BufferedReader bReader) throws IOException {
        String line = bReader.readLine();
        while (line != null) {
            if (OPENSSL_DSA_PARAMS_FOOTER.equals(line.trim())) {
                break;
            }
            line = bReader.readLine();
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the lines immediately after '-----END EC PARAMETERS-----' and confirm they begin with '-----BEGIN EC PRIVATE KEY-----'.
  2. Regenerate the EC key cleanly with 'openssl ecparam -genkey -name prime256v1 -out ec-key.pem'.
  3. If the EC PRIVATE KEY block lives in a separate file, point the config at that file rather than the parameters-only file.
Defensive patterns

Strategy: validation

Validate before calling

// For a file starting with EC PARAMETERS, confirm the next non-blank line after the EC PARAMETERS footer is the EC PRIVATE KEY header
static boolean ecParamsFollowedByEcKey(Path p) throws IOException {
    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
        String line; boolean sawParamsEnd = false;
        while ((line = r.readLine()) != null) {
            if (line.trim().equals("-----END EC PARAMETERS-----")) sawParamsEnd = true;
            else if (sawParamsEnd && line.trim().startsWith("-----BEGIN")) {
                return line.trim().equals("-----BEGIN EC PRIVATE KEY-----");
            }
        }
    }
    return false;
}

Try / catch

try { PemUtils.readPrivateKey(path, passwordSupplier); }
catch (IOException e) { if (e.getMessage().contains("EC Key header is missing")) { /* regenerate key */ } else throw e; }

Prevention

When it happens

Trigger: An EC PARAMETERS block is followed by something other than an EC PRIVATE KEY block (e.g. a DSA PARAMETERS block pasted in by mistake, a certificate body, or EOF); the file has EC PARAMETERS but the EC PRIVATE KEY header was deleted or renamed to 'RSA PRIVATE KEY'.

Common situations: Concatenating PEM files incorrectly (e.g. appending an EC PARAMETERS block to an RSA key); copy-paste errors when assembling a combined PEM; a corrupted archive that merged unrelated blocks.

Understand the failure class

Related errors


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