elastic/elasticsearch · error · IOException

Malformed PEM File, DEK-Info header is missing

Error message

Malformed PEM File, DEK-Info header is missing

What it means

Thrown by possiblyDecryptPKCS1Key when the PEM headers contain 'Proc-Type: 4,ENCRYPTED' but no 'DEK-Info' header is present. The DEK-Info header carries the cipher name and IV required to decrypt OpenSSL-format (PKCS#1/traditional) encrypted keys; without it decryption is impossible.

Source

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

     * Decrypts the password protected contents using the algorithm and IV that is specified in the PEM Headers of the file
     *
     * @param pemHeaders       The Proc-Type and DEK-Info PEM headers that have been extracted from the key file
     * @param keyContents      The key as a base64 encoded String
     * @param passwordSupplier A password supplier for the encrypted (password protected) key
     * @return the decrypted key bytes
     * @throws GeneralSecurityException if the key can't be decrypted
     * @throws IOException              if the PEM headers are missing or malformed
     */
    private static byte[] possiblyDecryptPKCS1Key(Map<String, String> pemHeaders, String keyContents, Supplier<char[]> passwordSupplier)
        throws GeneralSecurityException, IOException {
        byte[] keyBytes = Base64.getDecoder().decode(keyContents);
        String procType = pemHeaders.get("Proc-Type");
        if ("4,ENCRYPTED".equals(procType)) {
            // We only handle PEM encryption
            String encryptionParameters = pemHeaders.get("DEK-Info");
            if (null == encryptionParameters) {
                // malformed pem
                throw new IOException("Malformed PEM File, DEK-Info header is missing");
            }
            char[] password = passwordSupplier.get();
            if (password == null) {
                throw new IOException("cannot read encrypted key without a password");
            }
            Cipher cipher = getCipherFromParameters(encryptionParameters, password);
            byte[] decryptedKeyBytes = cipher.doFinal(keyBytes);
            return decryptedKeyBytes;
        }
        return keyBytes;
    }

    /**
     * Creates a {@link Cipher} from the contents of the DEK-Info header of a PEM file. RFC 1421 indicates that supported algorithms are
     * defined in RFC 1423. RFC 1423 only defines DES-CBS and triple DES (EDE) in CBC mode. AES in CBC mode is also widely used though ( 3
     * different variants of 128, 192, 256 bit keys )
     *
     * @param dekHeaderValue The value of the DEK-Info PEM header

View on GitHub (pinned to db6a809a66)

Solutions

  1. Open the file and confirm a 'DEK-Info: <algorithm>,<hex-iv>' line appears between the BEGIN header and the base64 body.
  2. Regenerate the encrypted key: 'openssl rsa -aes256 -in plain.key -out enc.key' (RSA) or 'openssl ec -aes256 -in plain.key -out enc.key' (EC).
  3. If you do not need encryption, export an unencrypted key: 'openssl rsa -in enc.key -out plain.key'.
Defensive patterns

Strategy: validation

Validate before calling

// For an OpenSSL-format key, confirm Proc-Type and DEK-Info headers exist together when encrypted
static boolean encryptedHeadersConsistent(Path p) throws IOException {
    boolean proc = false, dek = false;
    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
        String line;
        while ((line = r.readLine()) != null) {
            if (line.startsWith("Proc-Type:")) proc = line.contains("4,ENCRYPTED");
            if (line.startsWith("DEK-Info:")) dek = true;
        }
    }
    return !(proc && !dek);
}

Try / catch

try { PemUtils.readPrivateKey(path, passwordSupplier); }
catch (IOException e) { if (e.getMessage().contains("DEK-Info header is missing")) { /* restore header or regenerate */ } else throw e; }

Prevention

When it happens

Trigger: Loading an OpenSSL-format encrypted RSA/DSA/EC key whose 'DEK-Info:' line was deleted, truncated, or whose header was altered by a sanitiser that strips lines containing colons followed by hex; a hand-crafted encrypted key missing the DEK-Info line; a key whose Proc-Type indicates encryption but the file body is plain.

Common situations: Templating systems or text editors that strip lines starting with specific patterns; copy-paste that dropped the DEK-Info line; a key whose headers were reordered or partially removed; git filters that mangle PEM content.

Understand the failure class

Related errors


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