Skip to content

Commit ac48dc8

Browse files
committed
refactor crl
1 parent d67a575 commit ac48dc8

4 files changed

Lines changed: 170 additions & 135 deletions

File tree

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,55 @@
1-
# Spring Boot Module
1+
# Certificate Revocation and Path Validation Spring Boot Module
2+
3+
- X.509 digital certificates provide you with standardized formats that allow you to link public keys with particular
4+
entities in an otherwise device-independent fashion.
5+
- Certificate paths, or chains, provide a mechanism that allow you to recognize a given entity as trusted providing you
6+
trust the parties involved in creating the validation certificates leading up to that of the entity.
7+
8+
## Certificate Revocation Lists
9+
10+
- The original method for dealing with certificate revocation was to use certificate revocation lists, or CRLs. The
11+
concept is a fairly simple one to understand. In addition to the root certificate you are using to validate
12+
certificates that come your way, you have a CRL for the root certificate that contains a list of the certificates
13+
issued for that root certificate that have, for one reason or another, been revoked.
14+
- CRLs are distributed by a server and held by the client that needs them to check certificates.
15+
- As well as providing a blacklist of certificates, a CRL is also said to have a particular scope, and it is the scope
16+
that defines what certificates can end up in a CRL.
17+
- So, using CRLs to determine whether a given certificate is revoked involves finding a CRL of the correct scope and
18+
seeing if the certificate is present in it. The most general way of doing this in the JCA is provided by the CRL class
19+
in the java.security.cert package.
20+
- The CRL class provides a high-level abstraction of a certificate revocation list. It is a very simple abstract class
21+
with only a few methods on it.
22+
- The isRevoked() method takes a single Certificate object as a parameter and returns true if the certificate is present
23+
in the CRL.
24+
25+
## X.509 Certificate Revocation Lists
26+
27+
- Given a X.509 certificate, there are a couple of ways you might locate a valid CRL for it: It might be given to you,
28+
or the X.509 certificate may contain a CRL distribution points extension that gives you information on where to find
29+
the certificate.
30+
- The `java.security.cert.X509CRL` class provides the basic support for X.509 CRLs in the JCA
31+
- The X509CRLEntry class provides a type-safe way of representing the three fields contained in the SEQUENCE OF SEQUENCE
32+
contained in the revokedCertificates field in the TBSCertList.
33+
- The reason code extension is used to indicate the reason why the certificate has ended up in the CRL
34+
- The hold instruction code allows a certificate to be temporarily suspended, rather than revoked.
35+
- The invalidity date provides the date on which it is known, or suspected, that the certificate became
36+
invalid.
37+
- The certificate issuer extension is used to indicate who the real issuer of a certificate was.
38+
- The version 2 profile for CRLs introduced extensions. They provide extensions that take advantage of X.509
39+
certificate extensions.
40+
- The issuingDistributionPoint identifies the distribution point and scope for a particular CRL, and it indicates
41+
whether the CRL covers revocation for some factors.
42+
- The freshest CRL extension identifies how delta CRL information can be obtained for the CRL it is found in.
43+
44+
### Creating a CRL
45+
### Building a CRL Using the CertificateFactory
46+
47+
## Online Certificate Status Protocol
48+
49+
## Certificate Path Validation
50+
51+
## Building a Valid Path from a CertStore
252

353
## References
54+
455
- []()
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,106 @@
11
package com.javatmp.demo.crypto.crl;
22

3-
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
4-
import org.bouncycastle.asn1.x500.X500Name;
3+
import com.javatmp.demo.crypto.certificate.example.X509V1CreateExampleNew;
54
import org.bouncycastle.asn1.x509.BasicConstraints;
5+
import org.bouncycastle.asn1.x509.Extension;
66
import org.bouncycastle.asn1.x509.KeyUsage;
7-
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
8-
import org.bouncycastle.asn1.x509.X509Extensions;
97
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
8+
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
109
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
1110
import org.bouncycastle.jce.provider.BouncyCastleProvider;
1211
import org.bouncycastle.operator.ContentSigner;
13-
import org.bouncycastle.operator.OperatorCreationException;
1412
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
15-
import org.bouncycastle.x509.X509V1CertificateGenerator;
16-
import org.bouncycastle.x509.X509V3CertificateGenerator;
17-
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
1813

1914
import javax.security.auth.x500.X500Principal;
20-
import java.io.IOException;
2115
import java.math.BigInteger;
22-
import java.security.*;
23-
import java.security.cert.CertificateException;
16+
import java.security.KeyPair;
17+
import java.security.PrivateKey;
18+
import java.security.PublicKey;
2419
import java.security.cert.X509Certificate;
25-
import java.util.Calendar;
2620
import java.util.Date;
2721

2822
/**
2923
* Chapter 7 Utils
3024
*/
31-
public class Utils extends com.javatmp.demo.crypto.certificate.Utils
32-
{
25+
public class Utils extends com.javatmp.demo.crypto.certificate.Utils {
3326
private static final int VALIDITY_PERIOD = 7 * 24 * 60 * 60 * 1000; // one week
3427

35-
3628
/**
3729
* Generate a sample V1 certificate to use as a CA root certificate
3830
*/
3931
public static X509Certificate generateRootCert(KeyPair pair)
40-
throws Exception
41-
{
42-
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
43-
44-
certGen.setSerialNumber(BigInteger.valueOf(1));
45-
certGen.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
46-
certGen.setNotBefore(new Date(System.currentTimeMillis()));
47-
certGen.setNotAfter(new Date(System.currentTimeMillis() + VALIDITY_PERIOD));
48-
certGen.setSubjectDN(new X500Principal("CN=Test CA Certificate"));
49-
certGen.setPublicKey(pair.getPublic());
50-
certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
51-
52-
return certGen.generateX509Certificate(pair.getPrivate(), "BC");
32+
throws Exception {
33+
return X509V1CreateExampleNew.generateV1Certificate(pair,"CN=Test CA Certificate", "CN=Test CA Certificate",
34+
VALIDITY_PERIOD / 24 * 60 * 60 * 1000, "SHA1WithRSAEncryption");
5335
}
5436

5537
/**
5638
* Generate a sample V3 certificate to use as an intermediate CA certificate
5739
*/
58-
public static X509Certificate generateIntermediateCert(PublicKey intKey, PrivateKey caKey, X509Certificate caCert)
59-
throws Exception
60-
{
61-
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
62-
63-
certGen.setSerialNumber(BigInteger.valueOf(1));
64-
certGen.setIssuerDN(caCert.getSubjectX500Principal());
65-
certGen.setNotBefore(new Date(System.currentTimeMillis()));
66-
certGen.setNotAfter(new Date(System.currentTimeMillis() + VALIDITY_PERIOD));
67-
certGen.setSubjectDN(new X500Principal("CN=Test Intermediate Certificate"));
68-
certGen.setPublicKey(intKey);
69-
certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
70-
71-
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
72-
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifier(intKey.getEncoded()));
73-
certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(0));
74-
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));
75-
76-
return certGen.generateX509Certificate(caKey, "BC");
40+
public static X509Certificate generateIntermediateCert(
41+
PublicKey intKey, PrivateKey caKey, X509Certificate caCert)
42+
throws Exception {
43+
44+
JcaX509v3CertificateBuilder certBuilder =
45+
new JcaX509v3CertificateBuilder(
46+
caCert.getSubjectX500Principal(),
47+
BigInteger.valueOf(1),
48+
new Date(System.currentTimeMillis()),
49+
new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
50+
new X500Principal("CN=Test Intermediate Certificate"),
51+
intKey
52+
);
53+
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
54+
certBuilder.addExtension(Extension.authorityKeyIdentifier,
55+
false, utils.createAuthorityKeyIdentifier(caCert));
56+
certBuilder.addExtension(Extension.subjectKeyIdentifier,
57+
false, utils.createSubjectKeyIdentifier(intKey));
58+
certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
59+
certBuilder.addExtension(Extension.keyUsage, true,
60+
new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));
61+
62+
String issuerSignatureAlgorithm = "SHA256WithRSAEncryption"; // <-- Use appropriate signature algorithm based on your keyPair algorithm.
63+
ContentSigner issuerContentSigner =
64+
new JcaContentSignerBuilder(issuerSignatureAlgorithm)
65+
.build(caKey);
66+
67+
return new JcaX509CertificateConverter()
68+
.setProvider(BouncyCastleProvider.PROVIDER_NAME)
69+
.getCertificate(certBuilder.build(issuerContentSigner));
7770
}
7871

7972
/**
8073
* Generate a sample V3 certificate to use as an end entity certificate
8174
*/
82-
public static X509Certificate generateEndEntityCert(PublicKey entityKey, PrivateKey caKey, X509Certificate caCert)
83-
throws Exception
84-
{
85-
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
86-
87-
certGen.setSerialNumber(BigInteger.valueOf(1));
88-
certGen.setIssuerDN(caCert.getSubjectX500Principal());
89-
certGen.setNotBefore(new Date(System.currentTimeMillis()));
90-
certGen.setNotAfter(new Date(System.currentTimeMillis() + VALIDITY_PERIOD));
91-
certGen.setSubjectDN(new X500Principal("CN=Test End Certificate"));
92-
certGen.setPublicKey(entityKey);
93-
certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
94-
95-
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
96-
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifier(entityKey.getEncoded()));
97-
certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
98-
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
99-
100-
return certGen.generateX509Certificate(caKey, "BC");
101-
}
102-
103-
public static X509Certificate selfSign(KeyPair keyPair, String subjectDN) throws OperatorCreationException, CertificateException, IOException, CertificateException {
104-
Provider bcProvider = new BouncyCastleProvider();
105-
Security.addProvider(bcProvider);
106-
107-
long now = System.currentTimeMillis();
108-
Date startDate = new Date(now);
109-
110-
X500Name dnName = new X500Name(subjectDN);
111-
BigInteger certSerialNumber = new BigInteger(Long.toString(now)); // <-- Using the current timestamp as the certificate serial number
112-
113-
Calendar calendar = Calendar.getInstance();
114-
calendar.setTime(startDate);
115-
calendar.add(Calendar.YEAR, 1); // <-- 1 Yr validity
116-
117-
Date endDate = calendar.getTime();
118-
119-
String signatureAlgorithm = "SHA256WithRSA"; // <-- Use appropriate signature algorithm based on your keyPair algorithm.
120-
121-
ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate());
122-
123-
JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, startDate, endDate, dnName, keyPair.getPublic());
124-
125-
// Extensions --------------------------
126-
127-
// Basic Constraint
128-
BasicConstraints basicConstraints = new BasicConstraints(true); // <-- true for CA, false for EndEntity
129-
130-
certBuilder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, basicConstraints); // Basic Constraints is usually marked as critical.
131-
132-
// -------------------------------------
133-
134-
return new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(contentSigner));
75+
public static X509Certificate generateEndEntityCert(
76+
PublicKey entityKey, PrivateKey caKey, X509Certificate caCert)
77+
throws Exception {
78+
79+
JcaX509v3CertificateBuilder certBuilder =
80+
new JcaX509v3CertificateBuilder(
81+
caCert.getSubjectX500Principal(),
82+
BigInteger.valueOf(1),
83+
new Date(System.currentTimeMillis()),
84+
new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
85+
new X500Principal("CN=Test End Certificate"),
86+
entityKey
87+
);
88+
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
89+
certBuilder.addExtension(Extension.authorityKeyIdentifier,
90+
false, utils.createAuthorityKeyIdentifier(caCert));
91+
certBuilder.addExtension(Extension.subjectKeyIdentifier,
92+
false, utils.createSubjectKeyIdentifier(entityKey));
93+
certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
94+
certBuilder.addExtension(Extension.keyUsage, true,
95+
new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
96+
97+
String issuerSignatureAlgorithm = "SHA256WithRSAEncryption"; // <-- Use appropriate signature algorithm based on your keyPair algorithm.
98+
ContentSigner issuerContentSigner =
99+
new JcaContentSignerBuilder(issuerSignatureAlgorithm)
100+
.build(caKey);
101+
102+
return new JcaX509CertificateConverter()
103+
.setProvider(BouncyCastleProvider.PROVIDER_NAME)
104+
.getCertificate(certBuilder.build(issuerContentSigner));
135105
}
136106
}

JavaTMP-SpringBoot-Modules/spring-boot-cryptography/spring-boot-cryptography-crl/src/main/java/com/javatmp/demo/crypto/crl/example/X509CRLExample.java

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44
import org.bouncycastle.asn1.ASN1Enumerated;
55
import org.bouncycastle.asn1.x509.CRLNumber;
66
import org.bouncycastle.asn1.x509.CRLReason;
7-
import org.bouncycastle.asn1.x509.X509Extensions;
8-
import org.bouncycastle.x509.X509V2CRLGenerator;
9-
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
10-
import org.bouncycastle.x509.extension.X509ExtensionUtil;
7+
import org.bouncycastle.asn1.x509.Extension;
8+
import org.bouncycastle.cert.X509v2CRLBuilder;
9+
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
10+
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
11+
import org.bouncycastle.cert.jcajce.JcaX509v2CRLBuilder;
12+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
13+
import org.bouncycastle.operator.ContentSigner;
14+
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
1115

1216
import java.math.BigInteger;
1317
import java.security.KeyPair;
1418
import java.security.PrivateKey;
19+
import java.security.Security;
1520
import java.security.cert.X509CRL;
1621
import java.security.cert.X509CRLEntry;
1722
import java.security.cert.X509Certificate;
@@ -20,41 +25,52 @@
2025
/**
2126
* Basic Example of generating and using a CRL.
2227
*/
23-
public class X509CRLExample
24-
{
25-
public static X509CRL createCRL(
26-
X509Certificate caCert,
27-
PrivateKey caKey,
28-
BigInteger revokedSerialNumber)
29-
throws Exception
30-
{
31-
X509V2CRLGenerator crlGen = new X509V2CRLGenerator();
32-
Date now = new Date();
28+
public class X509CRLExample {
29+
static {
30+
// https://stackoverflow.com/questions/40975510/spring-boot-and-jca-providers
31+
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
32+
Security.addProvider(new BouncyCastleProvider());
33+
}
34+
}
3335

34-
crlGen.setIssuerDN(caCert.getSubjectX500Principal());
36+
public static X509CRL createCRL(X509Certificate caCert,
37+
PrivateKey caKey,
38+
BigInteger revokedSerialNumber)
39+
throws Exception {
40+
Date now = new Date();
41+
// X509v2CRLBuilder crlGen = new X509v2CRLBuilder(
42+
// new X500Name(caCert.getSubjectX500Principal().getName()),
43+
// now
44+
// );
45+
X509v2CRLBuilder crlGen = new JcaX509v2CRLBuilder(
46+
caCert.getSubjectX500Principal(),
47+
now
48+
);
3549

36-
crlGen.setThisUpdate(now);
3750
crlGen.setNextUpdate(new Date(now.getTime() + 100000));
38-
crlGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
3951

40-
crlGen.addCRLEntry(revokedSerialNumber, now, CRLReason.privilegeWithdrawn);
52+
ContentSigner signer =
53+
new JcaContentSignerBuilder("SHA256WithRSAEncryption")
54+
.build(caKey);
4155

42-
crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
43-
crlGen.addExtension(X509Extensions.CRLNumber, false, new CRLNumber(BigInteger.valueOf(1)));
56+
crlGen.addCRLEntry(revokedSerialNumber, now, CRLReason.privilegeWithdrawn);
57+
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
58+
crlGen.addExtension(Extension.authorityKeyIdentifier, false,
59+
utils.createAuthorityKeyIdentifier(caCert));
60+
crlGen.addExtension(Extension.cRLNumber, false, new CRLNumber(BigInteger.valueOf(1)));
4461

45-
return crlGen.generateX509CRL(caKey, "BC");
62+
return new JcaX509CRLConverter().getCRL(crlGen.build(signer));
4663
}
4764

4865
public static void main(String[] args)
49-
throws Exception
50-
{
66+
throws Exception {
5167
// create CA keys and certificate
52-
KeyPair caPair = Utils.generateRSAKeyPair();
53-
X509Certificate caCert = Utils.generateRootCert(caPair);
54-
BigInteger revokedSerialNumber = BigInteger.valueOf(2);
68+
KeyPair caPair = Utils.generateRSAKeyPair();
69+
X509Certificate caCert = Utils.generateRootCert(caPair);
70+
BigInteger revokedSerialNumber = BigInteger.valueOf(2);
5571

5672
// create a CRL revoking certificate number 2
57-
X509CRL crl = createCRL(caCert, caPair.getPrivate(), revokedSerialNumber);
73+
X509CRL crl = createCRL(caCert, caPair.getPrivate(), revokedSerialNumber);
5874

5975
// verify the CRL
6076
crl.verify(caCert.getPublicKey(), "BC");
@@ -65,13 +81,11 @@ public static void main(String[] args)
6581
System.out.println(" Certificate number: " + entry.getSerialNumber());
6682
System.out.println(" Issuer : " + crl.getIssuerX500Principal());
6783

68-
if (entry.hasExtensions())
69-
{
70-
byte[] ext = entry.getExtensionValue(X509Extensions.ReasonCode.getId());
84+
if (entry.hasExtensions()) {
85+
byte[] ext = entry.getExtensionValue(Extension.reasonCode.getId());
7186

72-
if (ext != null)
73-
{
74-
ASN1Enumerated reasonCode = (ASN1Enumerated )X509ExtensionUtil.fromExtensionValue(ext);
87+
if (ext != null) {
88+
ASN1Enumerated reasonCode = (ASN1Enumerated) JcaX509ExtensionUtils.parseExtensionValue(ext);
7589

7690
System.out.println(" Reason Code : " + reasonCode.getValue());
7791
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Spring Boot Module
22

33
## References
4-
- []()
4+
- [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security#Protocol_details)

0 commit comments

Comments
 (0)