{"record":{"id":"a13159833a44394b","repo":"elastic/elasticsearch","slug":"malformed-pem-file-dek-info-header-is-missing","errorCode":null,"errorMessage":"Malformed PEM File, DEK-Info header is missing","messagePattern":"Malformed PEM File, DEK-Info header is missing","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java","lineNumber":476,"sourceCode":"     * Decrypts the password protected contents using the algorithm and IV that is specified in the PEM Headers of the file\n     *\n     * @param pemHeaders       The Proc-Type and DEK-Info PEM headers that have been extracted from the key file\n     * @param keyContents      The key as a base64 encoded String\n     * @param passwordSupplier A password supplier for the encrypted (password protected) key\n     * @return the decrypted key bytes\n     * @throws GeneralSecurityException if the key can't be decrypted\n     * @throws IOException              if the PEM headers are missing or malformed\n     */\n    private static byte[] possiblyDecryptPKCS1Key(Map<String, String> pemHeaders, String keyContents, Supplier<char[]> passwordSupplier)\n        throws GeneralSecurityException, IOException {\n        byte[] keyBytes = Base64.getDecoder().decode(keyContents);\n        String procType = pemHeaders.get(\"Proc-Type\");\n        if (\"4,ENCRYPTED\".equals(procType)) {\n            // We only handle PEM encryption\n            String encryptionParameters = pemHeaders.get(\"DEK-Info\");\n            if (null == encryptionParameters) {\n                // malformed pem\n                throw new IOException(\"Malformed PEM File, DEK-Info header is missing\");\n            }\n            char[] password = passwordSupplier.get();\n            if (password == null) {\n                throw new IOException(\"cannot read encrypted key without a password\");\n            }\n            Cipher cipher = getCipherFromParameters(encryptionParameters, password);\n            byte[] decryptedKeyBytes = cipher.doFinal(keyBytes);\n            return decryptedKeyBytes;\n        }\n        return keyBytes;\n    }\n\n    /**\n     * Creates a {@link Cipher} from the contents of the DEK-Info header of a PEM file. RFC 1421 indicates that supported algorithms are\n     * 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\n     * different variants of 128, 192, 256 bit keys )\n     *\n     * @param dekHeaderValue The value of the DEK-Info PEM header","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java#L458-L494","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Open the file and confirm a 'DEK-Info: <algorithm>,<hex-iv>' line appears between the BEGIN header and the base64 body.","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).","If you do not need encryption, export an unencrypted key: 'openssl rsa -in enc.key -out plain.key'."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// For an OpenSSL-format key, confirm Proc-Type and DEK-Info headers exist together when encrypted\nstatic boolean encryptedHeadersConsistent(Path p) throws IOException {\n    boolean proc = false, dek = false;\n    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {\n        String line;\n        while ((line = r.readLine()) != null) {\n            if (line.startsWith(\"Proc-Type:\")) proc = line.contains(\"4,ENCRYPTED\");\n            if (line.startsWith(\"DEK-Info:\")) dek = true;\n        }\n    }\n    return !(proc && !dek);\n}","typeGuard":null,"tryCatchPattern":"try { PemUtils.readPrivateKey(path, passwordSupplier); }\ncatch (IOException e) { if (e.getMessage().contains(\"DEK-Info header is missing\")) { /* restore header or regenerate */ } else throw e; }","preventionTips":["Never hand-edit PEM headers; if a header is missing, regenerate the encrypted key.","Use 'openssl <algo> -aes256 -in plain.key -out enc.key' to produce well-formed encrypted PEMs.","Avoid templating systems that strip colon-prefixed lines."],"tags":["ssl","pem","encrypted","dek-info","config"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}