quarkusio/quarkus · error · SpiffeConnectionException

Leaf certificate must have 'digitalSignature' as key usage

Error message

Leaf certificate must have 'digitalSignature' as key usage

What it means

The leaf's KeyUsage extension must include the digitalSignature bit, since workload certificates are used to sign TLS handshakes and JWTs. If the extension exists but bit 0 is unset (or the array is empty), the validator rejects the certificate. Without digitalSignature the certificate cannot be used for the mTLS the extension establishes.

Source

Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java:30

    private static final String SPIFFE_URI_PREFIX = "spiffe://";
    private static final int URI_SAN_TYPE = 6;
    private static final int MAX_SPIFFE_ID_LENGTH = 2048;
    private static final int MAX_TRUST_DOMAIN_LENGTH = 255;

    private SpiffeValidator() {
    }

    static String validateLeaf(X509Certificate leaf) throws SpiffeConnectionException {
        if (leaf.getBasicConstraints() != -1) {
            throw new SpiffeConnectionException("Leaf certificate must not have CA flag set to true");
        }

        boolean[] keyUsage = leaf.getKeyUsage();
        if (keyUsage == null) {
            throw new SpiffeConnectionException("Leaf certificate is missing the key usage extension");
        }
        if (keyUsage.length < 1 || !keyUsage[0]) {
            throw new SpiffeConnectionException("Leaf certificate must have 'digitalSignature' as key usage");
        }
        if (keyUsage.length > 5 && keyUsage[5]) {
            throw new SpiffeConnectionException("Leaf certificate must not have 'keyCertSign' as key usage");
        }
        if (keyUsage.length > 6 && keyUsage[6]) {
            throw new SpiffeConnectionException("Leaf certificate must not have 'cRLSign' as key usage");
        }

        return extractAndValidateUriSan(leaf);
    }

    // X.509-SVID 3.2 SHOULD: signing cert SHOULD itself be an SVID (not enforced — upstream CA may not be SPIFFE-aware)
    // X.509-SVID 3.2 SHOULD: signing cert SHOULD reside in the trust domain of leaf SVIDs it issues (not enforced — cross-domain signing is allowed)
    static void validateIntermediate(X509Certificate cert) throws SpiffeConnectionException {
        if (cert.getBasicConstraints() < 0) {
            throw new SpiffeConnectionException(
                    "Signing certificate must have CA flag set to true: " + cert.getSubjectX500Principal());
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Reissue the certificate including digitalSignature in keyUsage (openssl -addext "keyUsage=digitalSignature,...").
  2. Use a proper test CA (e.g. cfssl or SPIRE's own tooling) that emits SPIFFE-compliant SVIDs.
  3. Inspect the cert: openssl x509 -noout -ext keyUsage and confirm Digital Signature is listed.
  4. If using a custom upstream CA, update its certificate template.

Example fix

// before
-addext "keyUsage=keyEncipherment"
// after
-addext "keyUsage=digitalSignature,keyEncipherment"
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasDigitalSignature(X509Certificate leaf) {
    boolean[] ku = leaf.getKeyUsage();
    return ku != null && ku.length > 0 && ku[0];
}

Type guard

static boolean isSignCapableLeaf(X509Certificate cert) {
    boolean[] ku = cert.getKeyUsage();
    return ku != null && ku.length > 0 && ku[0];
}

Try / catch

try {
    SpiffeValidator.validateLeaf(leaf);
} catch (SpiffeConnectionException e) {
    throw new CertificateException("Leaf cannot sign (missing digitalSignature): " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Validation encountering a leaf whose KeyUsage is present but does not assert digitalSignature — typically from hand-generated certificates with only keyEncipherment, keyAgreement, or nonRepudiation.

Common situations: Certificates created with keyUsage=keyEncipherment only; templates from internal PKIs copied for SPIFFE tests; tooling defaults that omit digitalSignature.

Understand the failure class

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ef99f7d733d2ed18. Report an issue: GitHub.