Recommended key usage for a client certificate

TL-DR SSL client cert doesn't need KeyUsage but if present it should be digitalSignature except for very-rare-if-ever fixed-*DH.

Caveat: You tagged SSL so I assume by "path that requires a certificate" you mean SSL/TLS or something over SSL/TLS (not necessarily HTTP/S). If you mean something more like CMS or S/MIME, or XML-sig, or even PGP, the answer may be different.

I'm surprised you don't find other references since X.509 certs are so widely used. My first page of google X.509 key usage extension gives PKIX rfc5280 which is the currently effective Internet spec and (the text form of) its predecessor rfc3280; the not-terribly-good wikipedia article; and https://access.redhat.com/documentation/en-US/Red_Hat_Certificate_System/8.0/html/Admin_Guide/Standard_X.509_v3_Certificate_Extensions.html which has (possibly over-) specific instructions for several cases including SSL client. Quoting the relevant part of 5280 (which your IBM site more or less copies):

   Bits in the KeyUsage type are used as follows:

      The digitalSignature bit is asserted when the subject public key
      is used for verifying digital signatures, other than signatures on
      certificates (bit 5) and CRLs (bit 6), such as those used in an
      entity authentication service, a data origin authentication
      service, and/or an integrity service.

      The nonRepudiation bit is asserted when the subject public key is
      used to verify digital signatures, other than signatures on
      certificates (bit 5) and CRLs (bit 6), used to provide a non-
      repudiation service that protects against the signing entity
      falsely denying some action.  In the case of later conflict, a
      reliable third party may determine the authenticity of the signed
      data.  (Note that recent editions of X.509 have renamed the
      nonRepudiation bit to contentCommitment.)

      The keyEncipherment bit is asserted when the subject public key is
      used for enciphering private or secret keys, i.e., for key
      transport.  For example, this bit shall be set when an RSA public
      key is to be used for encrypting a symmetric content-decryption
      key or an asymmetric private key.

      The dataEncipherment bit is asserted when the subject public key
      is used for directly enciphering raw user data without the use of
      an intermediate symmetric cipher.  Note that the use of this bit
      is extremely uncommon; almost all applications use key transport
      or key agreement to establish a symmetric key.


      The keyAgreement bit is asserted when the subject public key is
      used for key agreement.  For example, when a Diffie-Hellman key is
      to be used for key management, then this bit is set.

      The keyCertSign bit is asserted when the subject public key is
      used for verifying signatures on public key certificates.  If the
      keyCertSign bit is asserted, then the cA bit in the basic
      constraints extension (Section 4.2.1.9) MUST also be asserted.

      The cRLSign bit is asserted when the subject public key is used
      for verifying signatures on certificate revocation lists (e.g.,
      CRLs, delta CRLs, or ARLs).

      The meaning of the encipherOnly bit is undefined in the absence of
      the keyAgreement bit.  When the encipherOnly bit is asserted and
      the keyAgreement bit is also set, the subject public key may be
      used only for enciphering data while performing key agreement.

      The meaning of the decipherOnly bit is undefined in the absence of
      the keyAgreement bit.  When the decipherOnly bit is asserted and
      the keyAgreement bit is also set, the subject public key may be
      used only for deciphering data while performing key agreement.

This is necessarily somewhat general because X.509 (and PKIX) certs were designed to be used for a range of things, not just SSL/TLS, although that's the only usage most people know about. It does distinguish several types of signing, encryption, and keyagreement (which in practice is used for encryption).

5280/3280 only mandate KeyUsage for CA certs, implicitly leaving it optional for EE certs. I don't have actual X.509 but AFAIU it says if KeyUsage is not present it is treated as all bits set, because that is compatible with v1 and v2 before there were any extensions. CABforum baseline explicitly specifies it as required for CA certs but optional for "subscriber" (meaning EE) certs.

TLSv1.2 (or its predecessors) requires a client cert "allow ... signing" except for the fixed-DH and fixed-ECDH key-exchanges which no one seems to use at least on the public net, and related sections explain how except for fixed-*DH the client key is actually used only for signing handshake data to prove possession by and thus authenticate the client. This means if KeyUsage is present for SSL client it must include digitalSignature, and since in general a crypto key should not be used for multiple purposes without strong justification, KeyUsage for SSL client should not include anything else. If the client cert does not have KeyUsage or has a non-restrictive KeyUsage, a conforming SSL/TLS implementation will still use that key and cert only in the way specified by the protocol, which except fixed-*DH as noted is only signing/verifying data that is not a cert or CRL.


Here an answer for libNSS :

For libNSS used by Mozilla Firefox answer is hidden within ./certdb/certdb.c :

When actualy checking usage :

  case certUsageSSLClient:
    /* 
     * RFC 5280 lists digitalSignature and keyAgreement for
     * id-kp-clientAuth.  NSS does not support the *_fixed_dh and
     * *_fixed_ecdh client certificate types.
     */
    requiredKeyUsage = KU_DIGITAL_SIGNATURE;
    requiredCertType = NS_CERT_TYPE_SSL_CLIENT;

if KeyUsage extension is not set, then it behaves like if it was fully set :

/* if the extension is not present, then we allow all uses */
cert->keyUsage = KU_ALL;

if it set then , well, it is set

    if (keyUsage & PKIX_DIGITAL_SIGNATURE){
            nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
    }

NSS Cert Type should have NS_CERT_TYPE_SSL_CLIENT set. CertType is derived from EKU :

if no EKU then NS_CERT_TYPE_SSL_CLIENT is set.

/* If no NS Cert Type extension and no EKU extension, then */
nsCertType = 0;
...
/* allow any ssl or email (no ca or object signing. */
nsCertType |= NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER |
              NS_CERT_TYPE_EMAIL;

If there are EKU then NS_CERT_TYPE_SSL_CLIENT is set ONLY if not a CA.

if (findOIDinOIDSeqByTagNum(extKeyUsage,
                SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) ==
    SECSuccess){
    if (basicConstraintPresent == PR_TRUE &&
    (basicConstraint.isCA)) {
    nsCertType |= NS_CERT_TYPE_SSL_CA;
    } else {
    nsCertType |= NS_CERT_TYPE_SSL_CLIENT;
    }
}

So in practice for libNSS ( as got from mercurial reposoritory https://hg.mozilla.org/projects/nss on 25th October 2015 ) to be valid client certificate, it should match one of those assertions :

  • EKU AND KU are NOT set.
  • KU is not set AND EKU is set to clientAuth AND cert is NOT a CA.
  • KU contains digitalSignature AND EKU is NOT set
  • KU contains digitalSignature AND EKU is set to clientAuth AND cert is NOT a CA.