jwtk/jjwt · error · io.jsonwebtoken.security.InvalidKeyException

Invalid ${id} ASN.1 encoding: ${t.getMessage()}

Error message

Invalid ${id} ASN.1 encoding: ${t.getMessage()}

What it means

Edwards curve keys (Ed25519/Ed448/X25519/X448) are stored and exchanged via a fixed ASN.1 (PKCS#8/SubjectPublicKeyInfo-style) encoding prefixed by a curve-specific DER header. When EdwardsCurve.getKeyMaterial parses a key's encoded bytes and the ASN.1 structure fails to decode (or is out of bounds), the raw cause is wrapped into an InvalidKeyException with this message.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/EdwardsCurve.java:200

        this.PUBLIC_KEY_ASN1_PREFIX = publicKeyAsn1Prefix(this.encodedKeyByteLength, this.ASN1_OID);
        this.PRIVATE_KEY_ASN1_PREFIX = privateKeyPkcs8Prefix(this.encodedKeyByteLength, this.ASN1_OID, true);
        this.PRIVATE_KEY_JDK11_PREFIX = privateKeyPkcs8Prefix(this.encodedKeyByteLength, this.ASN1_OID, false);
    }

    @Override
    public int getKeyBitLength() {
        return this.keyBitLength;
    }

    public byte[] getKeyMaterial(Key key) {
        try {
            return doGetKeyMaterial(key); // can throw assertion and ArrayIndexOutOfBound exception on invalid input
        } catch (Throwable t) {
            if (t instanceof KeyException) { //propagate
                throw (KeyException) t;
            }
            String msg = "Invalid " + getId() + " ASN.1 encoding: " + t.getMessage();
            throw new InvalidKeyException(msg, t);
        }
    }

    /**
     * Parses the ASN.1-encoding of the specified key
     *
     * @param key the Edwards curve key
     * @return the key value, encoded according to <a href="https://www.rfc-editor.org/rfc/rfc8032">RFC 8032</a>
     * @throws RuntimeException if the key's encoded bytes do not reflect a validly ASN.1-encoded edwards key
     */
    protected byte[] doGetKeyMaterial(Key key) {
        byte[] encoded = KeysBridge.getEncoded(key);
        try {
            int i = Bytes.indexOf(encoded, ASN1_OID);
            Assert.gt(i, -1, "Missing or incorrect algorithm OID.");
            i = i + ASN1_OID.length;
            int keyLen = 0;
            if (encoded[i] == 0x05) { // NULL terminator, next should be zero byte indicator

View on GitHub (pinned to fb71496164)

Solutions

  1. Regenerate or re-export the key in standard PKCS#8 (private) / X.509 SPKI (public) DER format compatible with the curve.
  2. Do not strip or manually prepend the ASN.1 prefix bytes; let jjwt/JCE encode the key.
  3. Inspect the exception's cause (t) to see the exact ASN.1 parse failure and fix the encoding.
  4. Verify the key is actually an Edwards-curve key, not an ordinary EC key.

Example fix

// before: building a private key from raw seed bytes with wrong wrapping
PrivateKey key = new RawEdPrivateKey(seedBytes);
// after
KeyPair kp = Jwts.SIG.EdDSA.keyPair().build();
PrivateKey key = kp.getPrivate();
Defensive patterns

Strategy: try-catch

Validate before calling

byte[] enc = key.getEncoded();
if (enc == null || enc.length < 16) throw new IllegalArgumentException("Key has no/short encoded form; expected PKCS#8 or SPKI DER");

Try / catch

try {
  PublicKey pub = EdwardsCurve.Ed25519.toPublicKey(xBytes, null);
} catch (InvalidKeyException e) {
  // cause holds the ASN.1 parse error; fix the encoding
  Throwable cause = e.getCause();
}

Prevention

When it happens

Trigger: Passing a key whose encoded bytes do not follow the expected ASN.1 layout for the curve — e.g. a key generated/serialized by a different library format, an Ed25519 key bytes truncated or prefixed incorrectly, or feeding a non-Edwards key's bytes into EdwardsCurve parsing via findByKey/pkBytes/d/x.

Common situations: Interoperability with OpenSSL or other libraries that export keys in a different DER layout; manually constructing PrivateKey objects from raw bytes without the DER prefix; copy-paste corruption of base64 key material; using a P-256 EC key where an OKP key is expected.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/9ec6f20e2174827e. Report an issue: GitHub.