{"record":{"id":"3716a0d36deca0c1","repo":"elastic/elasticsearch","slug":"malformed-pem-file-dek-info-pem-header-is-invalid","errorCode":null,"errorMessage":"Malformed PEM file, DEK-Info PEM header is invalid","messagePattern":"Malformed PEM file, DEK-Info PEM header is invalid","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java","lineNumber":506,"sourceCode":"\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\n     * @param password       The password with which the key is encrypted\n     * @return a cipher of the appropriate algorithm and parameters to be used for decryption\n     * @throws GeneralSecurityException if the algorithm is not available in the used security provider, or if the key is inappropriate\n     * for the cipher\n     * @throws IOException if the DEK-Info PEM header is invalid\n     */\n    private static Cipher getCipherFromParameters(String dekHeaderValue, char[] password) throws GeneralSecurityException, IOException {\n        final String padding = \"PKCS5Padding\";\n        final SecretKey encryptionKey;\n        final String[] valueTokens = dekHeaderValue.split(\",\");\n        if (valueTokens.length != 2) {\n            throw new IOException(\"Malformed PEM file, DEK-Info PEM header is invalid\");\n        }\n        final String algorithm = valueTokens[0];\n        final String ivString = valueTokens[1];\n        final byte[] iv;\n        try {\n            iv = hexStringToByteArray(ivString);\n        } catch (IllegalArgumentException e) {\n            throw new IOException(\"Malformed PEM file, DEK-Info IV is invalid\", e);\n        }\n        if (\"DES-CBC\".equals(algorithm)) {\n            byte[] key = generateOpenSslKey(password, iv, 8);\n            encryptionKey = new SecretKeySpec(key, DEPRECATED_DES_ALGORITHM);\n        } else if (\"DES-EDE3-CBC\".equals(algorithm)) {\n            byte[] key = generateOpenSslKey(password, iv, 24);\n            encryptionKey = new SecretKeySpec(key, DEPRECATED_DES_EDE_ALGORITHM);\n        } else if (\"AES-128-CBC\".equals(algorithm)) {\n            byte[] key = generateOpenSslKey(password, iv, 16);\n            encryptionKey = new SecretKeySpec(key, \"AES\");","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java#L488-L524","documentation":"Thrown by getCipherFromParameters when the DEK-Info header value does not split into exactly two comma-separated tokens (algorithm, IV). The expected format is e.g. 'AES-256-CBC,A1B2C3...'; a value with no comma, multiple commas, or an empty value is rejected before any cryptographic operation.","triggerScenarios":"A DEK-Info header with only an algorithm and no IV, with extra commas, with whitespace inside tokens (the split does not trim the IV), or with a malformed value such as 'AES-256-CBC' alone; manual editing of the header; a sanitiser that rewrote the comma.","commonSituations":"Hand-edited or templated PEM files that altered the DEK-Info value; a copy-paste that lost the IV portion; a key produced by non-conformant tooling; locale-specific separators substituted for the comma.","solutions":["Inspect the 'DEK-Info:' line and confirm it has exactly the form '<ALGO>,<HEX-IV>' with a single comma and no spaces.","Regenerate the encrypted key with OpenSSL: 'openssl rsa -aes256 -in plain.key -out enc.key'.","If you cannot recover the original IV, you cannot decrypt the key; regenerate it from scratch."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the DEK-Info header has exactly two comma-separated tokens\nString dek = /* extracted DEK-Info value */;\nString[] tokens = dek.split(\",\");\nif (tokens.length != 2) {\n    throw new IllegalArgumentException(\"DEK-Info must be '<ALGO>,<HEX-IV>'\");\n}","typeGuard":null,"tryCatchPattern":"try { PemUtils.readPrivateKey(path, passwordSupplier); }\ncatch (IOException e) { if (e.getMessage().contains(\"DEK-Info PEM header is invalid\")) { /* fix header or regenerate */ } else throw e; }","preventionTips":["Do not hand-edit DEK-Info values.","Regenerate encrypted keys with OpenSSL to produce valid headers.","Lint PEM files with 'openssl <algo> -in <file> -noout -passin pass:<pw>'."],"tags":["ssl","pem","dek-info","encrypted","config"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}