1

Ok, so I have a method which is able to be passed a CRL and a certificate. I used it to validate the certificates coming from vendors during the runtime of my application.

The hardest part of this has been unit testing the damn thing!

I need to create a certificate file, and a CRL file, which I can then distribute as resources with the application, and then pass them in during the unit test.

I have the unit test written also, but with hard coded values - But now I need to know how to create the following :

two X509 Certificates. One CRL

I need the CRL to have an entry for one of the two X509 certs. This will allow me to test for revocation outcome, and also non-revocation.

I have tried the following guide, but security is far from my strong point - and I can't get it to work.

https://blog.didierstevens.com/2013/05/08/howto-make-your-own-cert-and-revocation-list-with-openssl/
MickeyThreeSheds
  • 986
  • 4
  • 23
  • 42
  • Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See [What topics can I ask about here](http://stackoverflow.com/help/on-topic) in the Help Center. Perhaps [Super User](http://superuser.com/) or [Unix & Linux Stack Exchange](http://unix.stackexchange.com/) would be a better place to ask. Also see [Where do I post questions about Dev Ops?](http://meta.stackexchange.com/q/134306) – jww Mar 07 '17 at 18:23
  • Also see [How do you sign Certificate Signing Request with your Certification Authority](http://stackoverflow.com/a/21340898/608639) and [How to create a self-signed certificate with openssl?](http://stackoverflow.com/q/10175812/608639) – jww Mar 07 '17 at 18:24

1 Answers1

3

Jamie Nguyen has a great guide on creating a Certificate Authority and issuing certificates and CRLs, which can be found here. This is what I will be loosely referring to while answering your question. If at any point you're curious what the output of these commands would look like, I refer you to his site. They are omitted here to keep this already long post manageable.

Basically we'll need to do the following:

  • Create a self-signed certificate to act as the Certificate Authority
  • Use the CA certificate to sign two leaf certificates
  • Revoke one of the leaf certificates
  • Publish a CRL

Creating Self-signed CA Certificate

First we'll need to prepare the CA configuration. If you don't want to go through his tutorial, you can simply use the following, somewhat abbreviated config:

# OpenSSL root CA configuration file.

[ ca ]
default_ca = ca_default

[ ca_default ]
dir               = /etc/pki/CA
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/db/root-ca.index
serial            = $dir/db/root-ca.serial
RANDFILE          = $dir/private/.rand
private_key       = $dir/private/root-ca.key
certificate       = $dir/certs/root-ca.crt
crlnumber         = $dir/db/root-ca.crlnumber
crl               = $dir/crl/root-ca.crl
crl_extensions    = crl_ext
default_crl_days  = 180
default_md        = sha384
name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose

[ policy_strict ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits        = 3072
distinguished_name  = req_distinguished_name
string_mask         = utf8only
default_md          = sha384
x509_extensions     = root_ca

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address
countryName_default             = US
stateOrProvinceName_default     = MD
localityName_default            =
0.organizationName_default      = LAB
organizationalUnitName_default  =
emailAddress_default            =

[ root_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
crlDistributionPoints = URI:http://pki.lab.local/int-ca.crl
authorityInfoAccess = caIssuers;URI:http://pki.lab.local/int-ca.crt

[ server_cert ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:http://pki.lab.local/int-ca.crl
authorityInfoAccess = caIssuers;URI:http://pki.lab.local/int-ca.crt

[ crl_ext ]
authorityKeyIdentifier=keyid:always
authorityInfoAccess = caIssuers;URI:http://pki.lab.local/int-ca.crt

This should be placed in the working directory as openssl.cnf.

You should modify the dir = /etc/pki/CA line to point to the directory you'll be working out of, and possibly change the CDP URLs to point to an actual domain if you want to enable revocation checking via CDP.

Next we'll need to create some files and directories expected by the CA, then generate an RSA private key for the CA certificate. Note: The CA private key will be protected with a passphrase.

mkdir db private certs crl newcerts csr & touch db/root-ca.index
echo 1000 > db/root-ca.serial & echo 1000 > db/root-ca.crlnumber
openssl genrsa -aes256 -out private/root-ca.key 4096

Now we need to generate a CA certificate using the new private key. You will be asked for the passphrase you entered when you created the private key, then prompted for some information such as Country, State, and Common Name. The common name field is what matters here, and for this test, I'd just put Test Root CA.

openssl req -config openssl.cnf -key private/root-ca.key \
    -new -x509 -days 3650 -sha256 -extensions root_ca \
    -out certs/root-ca.crt

Once the command completes successfully, you should see a new certificate at certs/root-ca.crt, which you can view with the following command:

openssl x509 -in certs/root-ca.crt -noout -text

Creating Leaf Certificates

To create leaf certificates (also known as end entity certificates) you'll need to generate another private key for each of them. We'll call them test1 and test2.

openssl genrsa -aes256 -out private/test1.key 4096
openssl genrsa -aes256 -out private/test2.key 4096

For each of these, you will generate a Certificate Signing Request (CSR) which the CA will use to generate the actual certificate. You'll be asked similar questions to when you created the CA certificate. You could just use Test 1 and Test 2 as the common names.

openssl req -config openssl.cnf -key private/test1.key
    -new -sha256 -out csr/test1.req
openssl req -config openssl.cnf -key private/test2.key
    -new -sha256 -out csr/test2.req

You should now have two certificate requests in the csr directory. We'll use these to generate the certificates. You'll need to enter the CA private key passphrase to sign these requests.

openssl ca -config openssl.cnf -in csr/test1.req -out certs/test1.crt \
    -extensions server_cert -days 365 -notext -md sha256
openssl ca -config openssl.cnf -in csr/test2.req -out certs/test2.crt \
    -extensions server_cert -days 365 -notext -md sha256

Now you should have two shiny new leaf certificates in the certs directory. They can be viewed with the below commands.

openssl x509 -in certs/test1.crt -noout -text
openssl x509 -in certs/test2.crt -noout -text

Revoking a Certificate

Now comes the fun part. The process of revoking a certificate is similar to the signing. We will use the CA cert and private key to revoke the leaf of Test 2. The following command will require the CA private key passphrase.

openssl ca -config openssl.cnf -revoke certs/test2.crt

If you're curious, the db/root-ca.index file, which till this point has been recording the serial numbers and timestamps of the certificates we issue, should now show a second revocation timestamp next to Test 2. It's a normal text file.

Publishing the CRL

Now to generate a CRL we simply do the following (requires CA private key passphrase):

openssl ca -config openssl.cnf -gencrl -out crl/root-ca.crl

Viewing the CRL is straightforward. Using the below command you should see an entry for the serial number of Test 2 and the timestamp of it's revocation.

openssl crl -in crl/root-ca.crl -noout -text

To verify the certificate has been revoked, the following command is used:

cat certs/root-ca.crt crl/root-ca.crl > crl/crl-chain.pem
openssl verify -crl_check -CAfile crl/crl-chain.pem certs/test2.crt

Using this for Test 2 should return a certificate status of revoked. Running the same comand for Test 1 should return OK.

Wrap Up

Assuming everything worked correctly, the end result should be:

  • One CA certificate in certs/root-ca.crt
  • One good leaf certificates in certs/test1.crt
  • One revoked leaf certificate in certs/test2.crt
  • One CRL in crl/root-ca.crl

Note 1: This is all assuming you will be using OpenSSL on a Linux machine. If you need instructions for windows and certutil they can be provided.

Note 2: I've omitted a lot from this guide that was not directly relevant to your question. If you want further details on this process, I refer you again to the link posted at the top.

AfroThundr
  • 1,175
  • 2
  • 17
  • 28