apache/pulsar · error · IllegalArgumentException

The ${alg.name()} algorithm does not support Key Pairs.

Error message

The ${alg.name()} algorithm does not support Key Pairs.

What it means

keyTypeForSignatureAlgorithm only maps RSA-family and ECDSA-family algorithms to a JCE KeyFactory type; any other SignatureAlgorithm reaches the else branch and throws IllegalArgumentException. It exists to support asymmetric (key-pair based) algorithms only.

Source

Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/utils/AuthTokenUtils.java:86

    public static PublicKey decodePublicKey(byte[] key, SignatureAlgorithm algType) throws IOException {
        try {
            X509EncodedKeySpec spec = new X509EncodedKeySpec(key);
            KeyFactory kf = KeyFactory.getInstance(keyTypeForSignatureAlgorithm(algType));
            return kf.generatePublic(spec);
        } catch (Exception e) {
            throw new IOException("Failed to decode public key", e);
        }
    }

    private static String keyTypeForSignatureAlgorithm(SignatureAlgorithm alg) {
        if (alg.getFamilyName().equals("RSA")) {
            return "RSA";
        } else if (alg.getFamilyName().equals("ECDSA")) {
            return "EC";
        } else {
            String msg = "The " + alg.name() + " algorithm does not support Key Pairs.";
            throw new IllegalArgumentException(msg);
        }
    }

    public static String encodeKeyBase64(Key key) {
        return Encoders.BASE64.encode(key.getEncoded());
    }

    public static String createToken(Key signingKey, String subject, Optional<Date> expiryTime,
                                     Optional<Map<String, Object>> headers) {
        JwtBuilder builder = Jwts.builder()
                .setSubject(subject)
                .signWith(signingKey);

        expiryTime.ifPresent(builder::setExpiration);
        headers.ifPresent(builder::setHeaderParams);

        return builder.compact();
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Switch the SignatureAlgorithm to an asymmetric one (RS256/RS512 or ES256/ES512) when using public/private key pairs.
  2. If you intend symmetric signing, use the secret-key API (a shared base64 secret) instead of key-pair/public-key APIs.
  3. Check broker.conf `tokenSigningAlgorithm`/client algorithm configuration for a leftover HSxxx value.

Example fix

// before
SignatureAlgorithm alg = SignatureAlgorithm.HS256; // symmetric, no key pair
PublicKey pk = AuthTokenUtils.decodePublicKey(keyBytes, alg);
// after
SignatureAlgorithm alg = SignatureAlgorithm.RS256; // asymmetric
PublicKey pk = AuthTokenUtils.decodePublicKey(keyBytes, alg);
Defensive patterns

Strategy: validation

Validate before calling

String fam = alg.getFamilyName();
if (!fam.equals("RSA") && !fam.equals("ECDSA")) throw new IllegalArgumentException("use RSA/ECDSA alg for key pairs, got " + alg);

Type guard

boolean isAsymmetric(SignatureAlgorithm alg) { return alg.getFamilyName().equals("RSA") || alg.getFamilyName().equals("ECDSA"); }

Try / catch

try { ...keyPairApi(alg); } catch (IllegalArgumentException e) { log.error("{}: use HSxxx with a shared secret instead", e.getMessage()); }

Prevention

When it happens

Trigger: Calling decodePublicKey or the key-pair generation path with an HMAC-family SignatureAlgorithm such as HS256, HS384, or HS512, since symmetric algorithms have no public/private key pair.

Common situations: Broker configured with `tokenSecretKey`-style settings while the algorithm is left at the JWT default HS256; copying configuration from a symmetric-token setup and switching the algorithm name without generating RSA/EC keys.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/b779ff75da39f4e2. Report an issue: GitHub.