elastic/elasticsearch · error · IOException

Invalid DER: can't handle UCS-4 string

Error message

Invalid DER: can't handle UCS-4 string

What it means

Thrown by Asn1Object.getString() when the parsed element has tag Type.UNIVERSAL_STRING (0x1C). UNIVERSAL_STRING encodes characters in UCS-4 (UTF-32), which this minimal DerParser explicitly does not support. The error is a deliberate unsupported-format rejection, not corruption.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java:261

                case Type.PRINTABLE_STRING:
                case Type.VIDEOTEX_STRING:
                case Type.IA5_STRING:
                case Type.GRAPHIC_STRING:
                case Type.ISO646_STRING:
                case Type.GENERAL_STRING:
                    encoding = "ISO-8859-1"; //$NON-NLS-1$
                    break;

                case Type.BMP_STRING:
                    encoding = "UTF-16BE"; //$NON-NLS-1$
                    break;

                case Type.UTF8_STRING:
                    encoding = "UTF-8"; //$NON-NLS-1$
                    break;

                case Type.UNIVERSAL_STRING:
                    throw new IOException("Invalid DER: can't handle UCS-4 string"); //$NON-NLS-1$

                default:
                    throw new IOException("Invalid DER: object is not a string"); //$NON-NLS-1$
            }

            return new String(value, encoding);
        }

        public String getOid() throws IOException {

            if (type != Type.OBJECT_OID) {
                throw new IOException("Ivalid DER: object is not object OID");
            }
            StringBuilder sb = new StringBuilder(64);
            switch (value[0] / 40) {
                case 0 -> sb.append('0');
                case 1 -> {
                    sb.append('1');

View on GitHub (pinned to db6a809a66)

Solutions

  1. Regenerate the key with a conformant tool (openssl) — UCS-4 UNIVERSAL_STRING is essentially never legitimate in private-key DER.
  2. Verify parser alignment with `openssl asn1parse -inform DER -in key.der`.
  3. Convert to PKCS#8 (`openssl pkcs8 -topk8`) so PemUtils uses the PKCS#8 path that does not call getString() on the private key.
  4. If you genuinely need UCS-4 support, pre-convert the string externally before invoking this parser.

Example fix

// before: EC key with non-standard encoding triggers UCS-4 path
PrivateKey pk = PemUtils.parsePrivateKey(ecKeyPath, passwordSupplier);

// after: re-encode to PKCS#8 which uses a different (OCTET STRING) field
// openssl pkcs8 -topk8 -in ec.pem -out ec.pk8.pem
PrivateKey pk = PemUtils.parsePrivateKey(pk8KeyPath, passwordSupplier);
Defensive patterns

Strategy: validation

Validate before calling

public static void requireNotUniversalString(DerParser.Asn1Object o) {
    if (o != null && o.getType() == DerParser.Type.UNIVERSAL_STRING) {
        throw new IllegalArgumentException("UNIVERSAL_STRING (UCS-4) is not supported; re-encode the key");
    }
}

Prevention

When it happens

Trigger: getString() is called on an ASN.1 element whose type byte is 0x1C. In practice this path is reached when parsing the private-key field of an EC key (parseEcDer line 604 calls getString()) where the encoding of the key octet-string element unexpectedly uses a UCS-4 string tag — extremely rare and almost always indicates the parser is misaligned.

Common situations: Misaligned DER causing a non-string element to be interpreted as a string tag, or a key generated by a tool that emits non-standard ASN.1 string types for fields the parser expects as OCTET_STRING.

Related errors


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