elastic/elasticsearch · error · IOException

Malformed PEM file, PEM footer is invalid or missing

Error message

Malformed PEM file, PEM footer is invalid or missing

What it means

Thrown by parsePKCS8 when, after the '-----BEGIN PRIVATE KEY-----' header, the scanner reaches EOF without finding '-----END PRIVATE KEY-----' or finds a different footer. The base64 body is collected line-by-line until the footer; absence of the footer means the key material is incomplete.

Source

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

     * PKCS#8
     *
     * @param bReader the {@link BufferedReader} containing the key file contents
     * @return {@link PrivateKey}
     * @throws IOException              if the file can't be read
     * @throws GeneralSecurityException if the private key can't be generated from the {@link PKCS8EncodedKeySpec}
     */
    private static PrivateKey parsePKCS8(BufferedReader bReader) throws IOException, GeneralSecurityException {
        StringBuilder sb = new StringBuilder();
        String line = bReader.readLine();
        while (line != null) {
            if (PKCS8_FOOTER.equals(line.trim())) {
                break;
            }
            sb.append(line.trim());
            line = bReader.readLine();
        }
        if (null == line || PKCS8_FOOTER.equals(line.trim()) == false) {
            throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
        }
        return parsePKCS8PemString(sb.toString());
    }

    /**
     * Creates a {@link PrivateKey} from a String that contains the PEM encoded representation of a plaintext private key encoded in PKCS8
     * @param pemString the PEM encoded representation of a plaintext private key encoded in PKCS8
     * @return {@link PrivateKey}
     * @throws IOException if the algorithm identifier can not be parsed from DER
     * @throws GeneralSecurityException if the private key can't be generated from the {@link PKCS8EncodedKeySpec}
     */
    public static PrivateKey parsePKCS8PemString(String pemString) throws IOException, GeneralSecurityException {
        byte[] keyBytes = Base64.getDecoder().decode(pemString);
        String keyAlgo = getKeyAlgorithmIdentifier(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(keyAlgo);
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Open the file and confirm both the BEGIN and END PRIVATE KEY markers are present and correctly spelled.
  2. Regenerate the PKCS#8 key: 'openssl pkcs8 -topk8 -inkey raw.key -out pkcs8.key -nocrypt'.
  3. Re-transfer the file in binary mode and verify checksums; strip stray characters with 'dos2unix' if the file came from Windows.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm both the PKCS#8 BEGIN and END markers are present
static boolean hasPkcs8Footer(Path p) throws IOException {
    boolean begin = false, end = false;
    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
        String line;
        while ((line = r.readLine()) != null) {
            if (line.trim().equals("-----BEGIN PRIVATE KEY-----")) begin = true;
            if (line.trim().equals("-----END PRIVATE KEY-----")) end = true;
        }
    }
    return begin && end;
}

Try / catch

try { PemUtils.readPrivateKey(path, passwordSupplier); }
catch (IOException e) { if (e.getMessage().contains("PEM footer is invalid or missing")) { /* re-issue key */ } else throw e; }

Prevention

When it happens

Trigger: A PKCS#8 PEM file whose '-----END PRIVATE KEY-----' line is missing, corrupted, or replaced by another marker; the file was truncated mid-body; the footer has trailing whitespace or CRLF that breaks the trimmed-equals check (note: line.trim() is applied, so plain spaces are tolerated but other invisible characters may not be).

Common situations: Truncated file from interrupted write or copy; templating system that strips END lines; an editor that auto-corrected the dash sequence; a file that was concatenating multiple keys and one was incomplete.

Understand the failure class

Related errors


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