18

I have a X509Certificate instance in Java and I need to identify if it is a CA certificate or user certificate.

Can anyone provide any help?

Thanks in advance!

Jurica Krizanic
  • 1,072
  • 2
  • 11
  • 26

3 Answers3

18

According to research I have performed, it can be checked by checking basic constraints! Check the API for returning results of getBasicConstraints() method.

So if the method returns result != -1, a certificate can be considered as a CA certificate.

I have checked this with several CA certificates (root and intermediate), and it works as described. I have also checked this method with several user certificates, and the method returns -1 as result.

Mihai Iorga
  • 39,330
  • 16
  • 106
  • 107
Jurica Krizanic
  • 1,072
  • 2
  • 11
  • 26
  • 1
    I think I have found an exception to this rule on Android. On most API versions ( greater that API 15) this works as described but on API17 it would return `!= -1` on both CA and user certificates. – JFreeman Dec 02 '15 at 01:57
  • Only on API17 or on API17+? I'm not involved in Android development, so I haven't tried out this on different API versions. – Jurica Krizanic Dec 02 '15 at 07:59
  • Only on API 17. I ended up using the double check - first `getBasicConstraints()!= -1` and after that `certificate.getKeyUsage()[5] == true`. My reading of Oracle documentation made me think this is possible and I have not found fault in this method so far. Here is a link to the documentation [X509Certificate Java6](http://docs.oracle.com/javase/6/docs/api/java/security/cert/X509Certificate.html#getBasicConstraints). Java 7 does not introduce changes to this functionality. – JFreeman Dec 02 '15 at 09:14
  • Is there some way using which we can also identify which (the name itself) CA actually signed the cert ? Checking the issuer name could be one way, I guess, but that may not be too reliable, I suppose. – qre0ct Dec 22 '15 at 16:22
  • I ended up checking `!certificate.getKeyUsage()[5]` Refer to answer by @dpinya – JFreeman Dec 29 '15 at 20:09
13

X509Certificate.getKeyUsage() javadoc:

gets a boolean array representing bits of the KeyUsage extension, (OID = 2.5.29.15). The key usage extension defines the purpose (e.g., encipherment, signature, certificate signing) of the key contained in the certificate. The ASN.1 definition for this is:

          KeyUsage ::= BIT STRING {
              digitalSignature        (0),
              nonRepudiation          (1),
              keyEncipherment         (2),
              dataEncipherment        (3),
              keyAgreement            (4),
              keyCertSign             (5),  --> true ONLY for CAs
              cRLSign                 (6),
              encipherOnly            (7),
              decipherOnly            (8) }

A certificate can be checked as follow:

X509Certificate cert = ...;
boolean[] keyUsage = cert.getKeyUsage();
if ( keyUsage[5] ) {
    // CA certificate
}
else {
    // User certificate
}
dpinya
  • 542
  • 7
  • 16
  • One may need to check if the `keyUsage` array is not null as `Returns null if this certificate does not contain a KeyUsage extension.` – sedovav Jun 22 '18 at 11:38
  • Key usage is not the same thing as Basic Constaints CA: true. You can have a CA: true certificate, without any key usage set. – Alex G Jun 28 '18 at 15:49
  • From RFC 5280, section "4.2.1.3. Key Usage": "Conforming CAs MUST include this extension in certificates that contain public keys that are used to validate digital signatures on other public key certificates or CRLs. When present, conforming CAs SHOULD mark this extension as critical". You can have a CA without key usage, but not a conformant CA. – dpinya Jun 29 '18 at 06:17
2

A Root CA will be a self signed certificate with the keyCertSign flag enabled. In most scenarios the common name may include the word CA for convenience. An intermediate CA certificate may be signed by a Root CA (or another Intermediate!). Your brower key store will have examples of commonly trusted CA certificates.

From The Internet Engineering Task Force

The keyCertSign bit is asserted when the subject public key is
    used for verifying a signature on certificates.  This bit may only
    be asserted in CA certificates.
Mihai Iorga
  • 39,330
  • 16
  • 106
  • 107
Anthony Palmer
  • 944
  • 10
  • 15
  • Oh, and look at slims answer for the how to in Java! – Anthony Palmer Aug 23 '12 at 13:26
  • Interoperability and standards out the window! Depending on your app, you will just have to make a call, i.e. guess CA, Client or provide some mechanism to let the user decide. Each of these scenarios are dangerous. You are probably caught in the hard place where you have usability vs security to balance. To strict and it dosent work, too lax and its a security hole. You might need to make the assumption that a users certificate chain must be signed by one of a set of allowable root CA's (e.g. ones included in JVM). I think you will have to provide options and force your supervisor to decide. – Anthony Palmer Aug 29 '12 at 09:18