jwtk/jjwt · error · SignatureException

Unable to compute ${getId()} signature with JCA algorithm '$

Error message

Unable to compute ${getId()} signature with JCA algorithm '${getJcaName()}' using key {${key}}: ${e.getMessage()}

What it means

AbstractSecureDigestAlgorithm.digest catches unexpected exceptions from the JCA Signature/Mac layer and rethrows them as SignatureException with algorithm id, JCA name, key description, and cause message. SignatureException and KeyException are propagated unchanged; anything else (e.g. NoSuchAlgorithmException, provider errors) is wrapped.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AbstractSecureDigestAlgorithm.java:54

        return signing ? "signing" : "verification";
    }

    protected abstract void validateKey(Key key, boolean signing);

    @Override
    public final byte[] digest(SecureRequest<InputStream, S> request) throws SecurityException {
        Assert.notNull(request, "Request cannot be null.");
        final S key = Assert.notNull(request.getKey(), "Signing key cannot be null.");
        Assert.notNull(request.getPayload(), "Request content cannot be null.");
        try {
            validateKey(key, true);
            return doDigest(request);
        } catch (SignatureException | KeyException e) {
            throw e; //propagate
        } catch (Exception e) {
            String msg = "Unable to compute " + getId() + " signature with JCA algorithm '" + getJcaName() + "' " +
                    "using key {" + KeysBridge.toString(key) + "}: " + e.getMessage();
            throw new SignatureException(msg, e);
        }
    }

    protected abstract byte[] doDigest(SecureRequest<InputStream, S> request) throws Exception;

    @Override
    public final boolean verify(VerifySecureDigestRequest<V> request) throws SecurityException {
        Assert.notNull(request, "Request cannot be null.");
        final V key = Assert.notNull(request.getKey(), "Verification key cannot be null.");
        Assert.notNull(request.getPayload(), "Request content cannot be null or empty.");
        Assert.notEmpty(request.getDigest(), "Request signature byte array cannot be null or empty.");
        try {
            validateKey(key, false);
            return doVerify(request);
        } catch (SignatureException | KeyException e) {
            throw e; //propagate
        } catch (Exception e) {
            String msg = "Unable to verify " + getId() + " signature with JCA algorithm '" + getJcaName() + "' " +

View on GitHub (pinned to fb71496164)

Solutions

  1. Inspect the wrapped cause via e.getCause() to find the JCA-level failure.
  2. Verify the JCA algorithm name is available: Signature.getInstance(name) works on your JVM.
  3. Ensure the key matches the algorithm family (e.g. an EC PrivateKey for ES256).
  4. Add/initialize the required security provider (Security.addProvider(new BouncyCastleProvider())).

Example fix

// before
byte[] sig = alg.sign(req); // may throw SignatureException: ... Caused by NoSuchAlgorithmException
// after
if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
byte[] sig = alg.sign(req);
Defensive patterns

Strategy: try-catch

Validate before calling

try { Signature.getInstance(alg.getJcaName()); } catch (NoSuchAlgorithmException e) { /* provider lacks algorithm */ }

Type guard

boolean canSign(Key k) { return k instanceof PrivateKey || k instanceof SecretKey; }

Try / catch

try { byte[] d = alg.digest(req); }
catch (SignatureException e) { throw new CryptoException("signing failed", e.getCause()); }

Prevention

When it happens

Trigger: Computing a signature where the underlying JCA operation fails: algorithm unavailable in the provider, key incompatible with the JCA algorithm, or an I/O error reading the payload stream.

Common situations: Missing JCE provider (e.g. no EdDSA provider on old JDKs); weak-key restrictions on some JVMs; wrong key class passed to the algorithm; corrupted payload stream.

Related errors


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