jwtk/jjwt · error · IllegalArgumentException
The algorithm does not support Key Pairs.
Error message
The algorithm does not support Key Pairs.
What it means
Deprecated Keys.keyPairFor(SignatureAlgorithm) throws IllegalArgumentException when the given algorithm is not an asymmetric signature algorithm, i.e. an HMAC algorithm like HS256 was requested as a KeyPair. MAC algorithms have no public/private pair.
Solutions
- Only call keyPairFor with asymmetric algorithms: RS256/RS384/RS512, PS256..PS512, ES256/ES384/ES512, EdDSA
- Use Keys.secretKeyFor(alg) or Jwts.SIG.HS256.key().build() for HMAC algorithms
- Guard with a check: if the algorithm name starts with "HS", generate a secret key instead
- Migrate to Jwts.SIG.<Alg>.keyPair().build() modern builder API
Example fix
// before KeyPair kp = Keys.keyPairFor(SignatureAlgorithm.HS256); // throws // after SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // HMAC has no keypair KeyPair kp = Keys.keyPairFor(SignatureAlgorithm.RS256); // asymmetric path
Defensive patterns
Strategy: type-guard
Validate before calling
if (alg.name().startsWith("HS")) throw new IllegalArgumentException(alg + " is HMAC; use secretKeyFor"); Type guard
static boolean isAsymmetric(io.jsonwebtoken.SignatureAlgorithm alg) {
return alg != null && !alg.name().startsWith("HS");
} Try / catch
try {
KeyPair kp = Keys.keyPairFor(alg);
} catch (IllegalArgumentException e) {
SecretKey sk = Keys.secretKeyFor(alg); // fall back to symmetric generation
} Prevention
- Validate algorithm family before key-pair generation in generic code paths
- Migrate to Jwts.SIG instances where MacAlgorithm vs SignatureAlgorithm typing makes misuse a compile error
- Document which SignatureAlgorithm constants are symmetric in shared utility APIs
When it happens
Trigger: Calling Keys.keyPairFor(SignatureAlgorithm.HS256) (or HS384/HS512) — the resolved SecureDigestAlgorithm is a MacAlgorithm, not the (new) SignatureAlgorithm interface, so key pair creation is rejected.
Common situations: Generic code that generates a key pair for any SignatureAlgorithm value; mixing HMAC and asymmetric algorithm constants; migration to 0.12.x where Jwts.SIG instances are used.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- The algorithm does not support shared secret keys.
- bitLength must be an even multiple of 8
- derivedKeyBitLength may not exceed
- EC JWK x,y coordinates do not exist on elliptic curve
- ECPublicKey's ECPoint does not exist on elliptic curve
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/91d48783a6995970.
Report an issue: GitHub.
Appendix: source
Thrown at api/src/main/java/io/jsonwebtoken/security/Keys.java:250
* <td>{@code secp521r1}</td>
* </tr>
* </table>
*
* @param alg the {@code SignatureAlgorithm} to inspect to determine which asymmetric algorithm to use.
* @return a new {@link KeyPair} suitable for use with the specified asymmetric algorithm.
* @throws IllegalArgumentException if {@code alg} is not an asymmetric algorithm
* @deprecated since 0.12.0 in favor of your preferred
* {@link io.jsonwebtoken.security.SignatureAlgorithm} instance's
* {@link SignatureAlgorithm#keyPair() keyPair()} builder method directly.
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated
public static KeyPair keyPairFor(io.jsonwebtoken.SignatureAlgorithm alg) throws IllegalArgumentException {
Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
SecureDigestAlgorithm<?, ?> salg = Jwts.SIG.get().get(alg.name());
if (!(salg instanceof SignatureAlgorithm)) {
String msg = "The " + alg.name() + " algorithm does not support Key Pairs.";
throw new IllegalArgumentException(msg);
}
SignatureAlgorithm asalg = ((SignatureAlgorithm) salg);
return asalg.keyPair().build();
}
/**
* Returns a new {@link Password} instance suitable for use with password-based key derivation algorithms.
*
* <p><b>Usage Note</b>: Using {@code Password}s outside of key derivation contexts will likely
* fail. See the {@link Password} JavaDoc for more, and also note the <b>Password Safety</b> section below.</p>
*
* <p><b>Password Safety</b></p>
*
* <p>Instances returned by this method use a <em>clone</em> of the specified {@code password} character array
* argument - changes to the argument array will NOT be reflected in the returned key, and vice versa. If you wish
* to clear a {@code Password} instance to ensure it is no longer usable, call its {@link Password#destroy()}
* method will clear/overwrite its internal cloned char array. Also note that each subsequent call to
* {@link Password#toCharArray()} will also return a new clone of the underlying password character array perView on GitHub (pinned to fb71496164)