X.509 Certificate Revocation Lists
X.509 Certificate Revocation Lists
Introduction
The Bouncy Castle APIs support the creation of version 2 X.509 Certificate Revocation Lists (CRLs) with the class:
org.bouncycastle.x509.X509V2CRLGenerator
Fuller details on CRL creation and their interpretation can be found in RFC 3280 Section 5.
Avaliable Algorithms
DSA
DSA currently just supports SHA-1. The following value can be used in place of the variable signatureAlgorithm in the examples below:
- SHA1withDSA
Elliptic Curve (ECDSA)
ECDSA is support with both the SHA-1 and SHA-2 family of digest algorithms. The following values can be used in place of the variable signatureAlgorithm in the examples below:
- SHA1withECDSA
- SHA224withECDSA
- SHA256withECDSA
- SHA384withECDSA
- SHA512withECDSA
RSA
A variety of digests can be used to sign CRLs using the RSA algorithm. The following value can be used in place of the variable signatureAlgorithm in the examples below:
- MD2withRSA
- MD5withRSA
- SHA1withRSA
- SHA224withRSA
- SHA256withRSA
- SHA384withRSA
- SHA512withRSA
- RIPEMD160withRSA
- RIPEMD128withRSA
- RIPEMD256withRSA
Creating a Basic CRL
A basic CRL just includes the some details about the issuing CA, the CRL, and details of the certificates that have been revoked as well as when they have been revoked. At a minimum a CRL should contain extensions giving the identity of the certificate used to sign the CRL and the number of the CRL to make it easier for clients using the CRL to recognise it.
The following code generates a basic CRL revoking the certificate with the number 1 that was issued by a particular CA. The code labels the CRL as being issued at the time now and also provides a time at which a new update should have been received by providing nextUpdate. A CRL entry is added using the addCRLEntry() method with the reason for the revocation been given as privilegeWithdrawn. Two extensions are added describing the certificate that can be used to verify the CRL and assigning a number to the CRL and then the CRL is generated.
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.x509.X509V2CRLGenerator;
...
X509V2CRLGenerator crlGen = new X509V2CRLGenerator();
Date now = new Date();
Date nextUpdate = ...;
X509Certificate caCrlCert = ...;
PrivateKey caCrlPrivateKey = ...;
crlGen.setIssuerDN(new X500Principal("CN=Test CA"));
crlGen.setThisUpdate(now);
crlGen.setNextUpdate(nextUpdate);
crlGen.setSignatureAlgorithm(signatureAlgorithm);
crlGen.addCRLEntry(BigInteger.ONE, now, CRLReason.privilegeWithdrawn);
crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier,
false, new AuthorityKeyIdentifierStructure(caCrlCert));
crlGen.addExtension(X509Extensions.CRLNumber,
false, new CRLNumber(crlNumber));
X509CRL crl = crlGen.generateX509CRL(caCrlPrivateKey, "BC");
As the code suggests the extensions are constructed in the same way as those for certificates.
Updating an Existing CRL
Often you just need to add another entry to an already existing CRL. The Bouncy Castle APIs provide a addCRL() method to do this, so, for example, if we discovered that we had to revoke the certificate with serial number 2 we could include our previous CRL using code similar to the following:
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.x509.X509V2CRLGenerator;
...
X509V2CRLGenerator crlGen = new X509V2CRLGenerator();
Date nextUpdate = ...;
X509Certificate caCrlCert = ...;
PrivateKey caCrlPrivateKey = ...;
X509CRL existingCRL = ...
crlGen.setIssuerDN(new X500Principal("CN=Test CA"));
crlGen.setThisUpdate(now);
crlGen.setNextUpdate(nextUpdate);
crlGen.setSignatureAlgorithm(signatureAlgorithm);
crlGen.addCRL(existingCRL);
crlGen.addCRLEntry(BigInteger.valueOf(2), now, CRLReason.privilegeWithdrawn);
crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier,
false, new AuthorityKeyIdentifierStructure(caCrlCert));
crlGen.addExtension(X509Extensions.CRLNumber,
false, new CRLNumber(crlNumber));
X509CRL crl = crlGen.generateX509CRL(pair.getPrivate(), "BC");