jwtk/jjwt · error · InvalidKeyException

${familyName} ${keyType} keys must be SecretKey instances.

Error message

${familyName} ${keyType} keys must be SecretKey instances.

What it means

Type guard inside SignatureAlgorithm.assertValid: when the algorithm is an HMAC family member (HS256/HS384/HS512), the JCA Signature for HMAC-SHA only accepts symmetric keys, so any key that is not a javax.crypto.SecretKey (e.g. an RSA PrivateKey or EC PublicKey passed to an HS* algorithm) is rejected with InvalidKeyException.

Source

Thrown at api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java:356

    private static String keyType(boolean signing) {
        return signing ? "signing" : "verification";
    }

    /**
     * @since 0.10.0
     */
    private void assertValid(Key key, boolean signing) throws InvalidKeyException {

        if (this == NONE) {

            String msg = "The 'NONE' signature algorithm does not support cryptographic keys.";
            throw new InvalidKeyException(msg);

        } else if (isHmac()) {

            if (!(key instanceof SecretKey)) {
                String msg = this.familyName + " " + keyType(signing) + " keys must be SecretKey instances.";
                throw new InvalidKeyException(msg);
            }
            SecretKey secretKey = (SecretKey) key;

            byte[] encoded = EMPTY_BYTES;
            try {
                encoded = secretKey.getEncoded();
                if (encoded == null) {
                    throw new InvalidKeyException("The " + keyType(signing) + " key's encoded bytes cannot be null.");
                }

                String alg = secretKey.getAlgorithm();
                if (alg == null) {
                    throw new InvalidKeyException("The " + keyType(signing) + " key's algorithm cannot be null.");
                }

                // These next checks use equalsIgnoreCase per https://github.com/jwtk/jjwt/issues/381#issuecomment-412912272
                if (!HS256.jcaName.equalsIgnoreCase(alg) &&
                        !HS384.jcaName.equalsIgnoreCase(alg) &&

View on GitHub (pinned to fb71496164)

Solutions

  1. Use a SecretKey with HMAC algorithms; create one via Keys.secretKeyFor(SignatureAlgorithm.HS256) (or HS384/HS512).
  2. If the key is asymmetric (RSA/EC), switch the algorithm to the matching family (RS*/PS* for RSAKey, ES* for ECKey).
  3. For string/byte-array secrets, wrap them with new SecretKeySpec(bytes, "HmacSHA256") matching the algorithm's JCA name.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java:356 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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