{"record":{"id":"47279d108cf12473","repo":"elastic/elasticsearch","slug":"invalid-der-length-too-short","errorCode":null,"errorMessage":"Invalid DER: length too short","messagePattern":"Invalid DER: length too short","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java","lineNumber":139,"sourceCode":"     *\n     * @return The length as integer\n     */\n    private int getLength() throws IOException {\n\n        int i = derInputStream.read();\n        if (i == -1) throw new IOException(\"Invalid DER: length missing\");\n\n        // A single byte short length\n        if ((i & ~0x7F) == 0) return i;\n\n        int num = i & 0x7F;\n\n        // We can't handle length longer than 4 bytes\n        if (i >= 0xFF || num > 4) throw new IOException(\"Invalid DER: length field too big (\" + i + \")\"); //$NON-NLS-2$\n\n        byte[] bytes = new byte[num];\n        int n = derInputStream.read(bytes);\n        if (n < num) throw new IOException(\"Invalid DER: length too short\");\n\n        int len = new BigInteger(1, bytes).intValue();\n        if (len < 0) {\n            throw new IOException(\"Invalid DER: length larger than max-int\");\n        }\n\n        return len;\n    }\n\n    /**\n     * An ASN.1 TLV. The object is not parsed. It can\n     * only handle integers.\n     *\n     * @author zhang\n     */\n    public static class Asn1Object {\n\n        protected final int type;","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java#L121-L157","documentation":"Thrown by DerParser.getLength() when the long-form length header declared N continuation octets but InputStream.read(bytes) returned fewer than N. The length-of-length byte was plausible (<=4) but the stream was truncated right after it.","triggerScenarios":"getLength() enters long form, computes num = i & 0x7F (1..4), allocates bytes[num], then derInputStream.read(bytes) returns n < num. Common when the DER is cut off in the middle of a multi-byte length field.","commonSituations":"Truncated download, copy/paste that dropped bytes from a binary DER file, base64 corruption that lost trailing characters, or a buffer that was sliced one or two bytes too short.","solutions":["Re-fetch or re-export the key; truncation is the dominant cause.","Validate file size against a known-good reference.","If you build the byte[] in code, double-check the slice bounds.","Cross-check with `openssl asn1parse -inform DER -in key.der` — it will report a similar short-read."],"exampleFix":"// before: trailing bytes lost during transfer\nbyte[] shortDer = Arrays.copyOfRange(fullDer, 0, fullDer.length - 2);\nnew DerParser(shortDer).readAsn1Object();\n\n// after: use full file\nbyte[] fullDer = Files.readAllBytes(Path.of(\"key.der\"));\nnew DerParser(fullDer).readAsn1Object();","handlingStrategy":"validation","validationCode":"private static void requireLengthBytesPresent(byte[] der, int idx, int num) {\n    if (idx + num > der.length) {\n        throw new IllegalArgumentException(\"length-of-length declares \" + num + \" bytes but only \" + (der.length - idx) + \" remain\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the byte[] length covers the declared length-of-length before parsing.","Use sha256 checksums to catch truncation after file transfers.","Slice DER buffers using the outer SEQUENCE length, not guessed offsets."],"tags":["ssl","der","asn1","keystore","elasticsearch","crypto"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}