L0130 Make Your Own CA Part 1

OpenSSL can be used to create a CA that we manage. A private CA is useful for creating an internal PKI and gaining control over internally used certificates. A private CA can be the best solution in networks that do not have access to the Internet. Without the Internet, it is not possible to access commercial CRL and OCSP services.

For larger projects, enterprises use dedicated software that provides web interface, access control, auditing. Examples of such software are Dogtag Certificate System, Microsoft Active Directory Certificate Services, HashiCorp Vault.

Creation of Your Own CA

We will use name "myCA" to refer to CA that we will create.

Directory Structure

Everything needed for "myCA" must be placed into one directory system. At the top we will have "myCA" folder, other files/folders are inside of the "myCA" folder.

privateThis is a folder where we will store the "myCA" private key.
newcertsEvery certificate signed by the "myCA" will be stored here. Names of the files will be certificate serial numbers. This folder is used by OpenSSL to keep track of issued certificates, revocations, and duplicates.
index.txtThis is file that stores a list of all of the issued certificates.
V 280101120000Z 1000 unknown /CN=server1    # valid
E 280101120000Z 1001 unknown /CN=server2    # expired
R 270501120000Z 1002 unknown /CN=oldserver  # revoked
serial.txtThis file will store the serial number for a new certificate. If that number is "X", the next certificate will be given serial number "X", and OpenSSL will update this text file to store the next serial number, which would be "X+1".
certsThis directory is optional. Here we can place any certificate, and we can give meaningful names to those files. We can store here "myCA" certificate, and we can organize certificate chains for deployment.
csrConvinient folder where we can place intermediate CA CSR's.
crlThis is folder where we keep our CRL list.
crlnumber.txtThis file is similar to "serial". It holds the number for the next version of CRL list.
myCA.cnfThis is configuration file used by the "myCA".

Creation of a Directory Structure

We will create files/folders needed for "myCA". We will place initial values into some of the files.

cd /home/fff/Desktop      This is our current directory. 
mkdir myCAWe will make root folder. We will jump to that folder.cd myCA
mkdir privateThis empty folder is for a private key. 
mkdir newcertsIssued certificates will be stored here. 
touch index.txtHere we will register newly issued certificates. 
touch serial.txtInside of this file we will write initial hexadecimal serial number 2730.echo 2730 > serial.txt #even number of digits
mkdir certsThis folder is optional. 
mkdir csrHere we will place CSRs for intermediate CAs. 
mkdir crlEmpty folder for CRL file. 
touch crlnumber.txtWe will set initial hexadecimal serial number for CRLs, in this file.echo 2730 > crlnumber.txt #even number of digits

Creation of OpenSSL Configuration File

[ca]
default_ca = CA_default
This section will direct us toward "CA_default" section.
[CA_default]
private_key       = ./private/myCA.key
new_certs_dir     = ./newcerts
database          = ./index.txt
serial            = ./serial.txt
certs             = ./certs
certificate       = ./certs/myCA.crt
crl_dir           = ./crl
crl               = ./crl/myCA.crl
crlnumber         = ./crlnumber.txt
default_days      = 730
default_crl_days  = 30
default_md        = sha256
copy_extensions   = none
crl_extensions    = crl_ext
x509_extensions   = v3_intermediate_ca
policy            = policy_intermediate_ca
unique_subject    = no
This section is the major section. Here we will write locations of all of the main folders and files, and other CA related data.

Option "x509_extensions" refers to default extensions that CA will use when it signs some certificate. Because this CA will only sign intermediate CA's certificates, we will be explicit and we will place those extensions in the section "v3_intermediate_ca".

Section "policy" will refer to section where we will specify what Distinguish Name values ( Country, State, City ) must match between intermediate CA CSR and this configuration file.

New option is "copy-extension". That means that none of the intermediate CA CSR extensions will be copied to certificate. Ony extensions specified in the section "v3_intermediate_ca" will be used. We want the full control.

Option "unique_subject" will allow us to issue several certificates for the same Subject. Without this option, we will be prohibited to have two valid certificates for the same subject in "index.txt".
[req]
default_md = sha256
prompt = no
distinguished_name = ca_dn
x509_extensions    = v3_ca
Here we will place data that will define characteristics of the CA self-signed certificate.
[ca_dn]
countryName            = RS
stateOrProvinceName    = Serbia
localityName           = Belgrade
organizationName       = CA organization
organizationalUnitName = CA unit
commonName             = Root CA
This is a section for distinguished name for the CA self-signed certificate.
[v3_ca]                                                    
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:true,pathlen:1
keyUsage = critical,digitalSignature,  \            cRLSign,keyCertSign
These extensions will be added to CA certificate. Pathlen is set to 1 because we only allow one intermediate CA.

Here we can see keyword "always". This keyword means that if we can not include some element ( key hash in this case ) in a certificate, then creation of a certificate should fail.

[policy_intermediate_ca]         
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied  
This section will tell what options from the CSR must match options in "myCA.cnf" file. Possible values are "match, supplied, optional".
- match     >   the values must match. If they do not match, we will not be able to sign CSR.
- supplied  >   option must exist, but it does not have to have the same value as in "myCA.cnf" file.
- optional  >   we can do whatever.

For internal CA, we should mostly use "optional".

[v3_intermediate_ca]
subjectKeyIdentifier    = hash

authorityKeyIdentifier  = keyid:always,issuer
basicConstraints        = critical,CA:true,pathlen:0
keyUsage                = critical,keyCertSign,cRLSign
crlDistributionPoints   = @ca_crl_distribution_point

[ca_crl_distribution_point]
URI.0                   = http://ca.example.com/myCa.crl

[crl_ext]
authorityKeyIdentifier  = keyid:always
These are extensions that will be added to intermediate CA certificates.

Notice that we are using the sign "@" for "crlDistributionPoints". Some options expect a section name so there is no need for "@" sign. This option "crlDistributionPoints" is not expecting a section name. That is why in this case we use "@" prefix.

We can notice that only sections "ca" and "req" are colored in black. They are the main sections that must exist. Every other section is just for better organization, must be referenced from somewhere, and can be named anyway we like.

Sections "req, ca_dn, v3_ca" are for the self signed CA certificate. Sections "policy_intermediate_ca" and "v3_intermediate_ca" are for the certificates of the intermediate CAs.

We will create configuration file "touch myCA.cnf", and we will copy the text from above into that file.

Random Serial Numbers

Inside of the [CA_default] section, we can have this option. If we use this option, then the "serial" file will be unused.
rand_serial = yes
This option means that serial number of certificates will not be serial number ( 1000, 1001, 1002… ). Instead of that, it will be random hexadecimal number ( 4F8A91D03B7E2C11, A93C72E5B18D904F…).

We should use this option set to "yes". That would make our setup safer, and it is recommended. I will not set it to "yes" in my example. Instead of that I used random number 2730 as my first serial number. This is usually enough to distinguish serial numbers from "myCA" and some other internal CA that could also exist in our organization.

We should always have file "serial" file. Some OpenSSL commands and external tools expect this file to be present.

Permissions of the Files and Folders

Now that we have all of the files and folders, we can protect them. I will not apply these permissions because this is just educational demonstration, but in production these are the levels of protection that you need. I will remind you that "4 (read) + 2 (write) + 1 (execute) = 7".

chmod 700 /home/fff/Desktop/myCAOnly administrator should have access to "myCA" folder.
chmod 700 private
chmod 600 private/*
It is the same for a "private" folder and its content.
chmod 755 newcerts chmod 644 newcerts/*Certificates are public. For them we can put less restrictive permissions.
chmod 600 index.txtIndex file is important for functioning of the CA, so we will protect it strictly.
chmod 600 serialThe same as for "index.txt", because messing with this folder can corrupt CA.
chmod 755 certs chmod 644 certs/*This is the same as for "newcerts" folder.
chmod 755 csr chmod 644 csr/*These are the permissions for CSRs.
chmod 755 crl chmod 644 crl/*CRLs are public information. The same as for certificates.
chmod 600 crlnumber chmod 600 crlnumber/*It is recommended that only root has access to this folder.
chmod 644 myCA.cnfConfiguration file should be protected, too.

Creation of the CA Private Key and Certificate

We will create the CA private key and we will place it into "private" folder.openssl genpkey -algorithm ed25519 -out private/myCA.key

Now that we have a key, we can create CA CSR file. For it, we have to provide the name of a configuration file.
openssl req -config myCA.cnf -new -key private/myCA.key -out csr/myCA.csr

Inside of the CSR file we can see our Subject, and no Extensions.
openssl req -in csr/myCA.csr -noout -text  

We will sign CA certificate using x509 command. We will use extensions from v3_ca section. Note that when we create a certificate with "-x509" command, there will be no new entry in "index.txt, newcerts or serial.txt". There is no need to register CA certificate.

openssl req -new -x509 -config myCA.cnf -key private/myCA.key -extensions v3_ca -out certs/myCA.crt 
When we use "ca" command for signing, only then there will be changes in the "index.txt, serial.txt, newcerts". For selfsigning CA certificate we don't need that. That is why we will use ordinary "-x509" command.

We can read from the newly create certificate.  
openssl x509 -in certs/myCA.crt -noout -text

We can notice one thing. There is no "issuer" for "Authority Key Identifier", we only have "keyID". This is normal because we are using self signed certificate, so there is no need for repetition. Subject and Authority are the same.
openssl verify -CAfile certs/myCA.crt certs/myCA.crtcerts/myCA.crt: OK    # We can verify certificate.

CRL

We can use "ca" command to create CRL file.openssl ca -config myCA.cnf -gencrl -out crl/myCA.crl
A new file will be created inside of the "crl" folder. This file will look like any other certificate or key, some text and base64 encoding between. Inside of the "crlnumber.txt" file, a number will increase by 1, and will become 2730 + 1 = 2731.
One new file will appear. This is a copy of "crlnumber.txt" file. It will have the old CRL serial number 2730.

We can read from the CRL file. We will see inside that there are no revoked certificates.  
openssl crl -in crl/myCA.crl -noout -text
We will verify the CRL file.
openssl crl -in crl/myCA.crl -CAfile certs/myCA.crt -noout -verify

# scp crl/myCa.crl webserver:/var/www/html/myCa.crlWe must copy the CRL file onto web server for download.

Certificate Revocation

This is how we revoke the certificate we made.  
openssl ca -config myCA.cnf -revoke certs/myCA.crt -crl_reason keyCompromise

These are the possible values for "-crl_reason".

unspecifiedkeyCompromiseCACompromiseaffiliationChangedsuperseededcessationOfOperationprivilegeWithdrawn
No specific reason.Subject private key is compromised.CA private key is compromised.Subject had organizational change.A new certificate is issued.Subject is closed.Usage and constraints of a certificate are changed.

Revoked certificate will be registered in the "index.txt" file. Letter "R" means that this certificate is Revoked.
cat index.txt

The first time we write something into "index.txt" database, the new files could appear. The file "index.txt.old" is backup of the "index.txt" file. In our case it is empty, because there was nothing in the "index.txt" file previously.
The file "index.txt.attr" contains the value of the option "unique_subject = no".

Crating a New CA Key and Certificate

We will again create the CA key and certificate.openssl genpkey -algorithm ed25519 -out private/myCA.key
openssl req -config myCA.cnf -new -key private/myCA.key -out csr/myCA.csr
openssl req -new -x509 -config myCA.cnf -key private/myCA.key -extensions v3_ca -out certs/myCA.crt

                                                                                                                                                                                                         

Now that we have a new key, we will create a new CRL file.
openssl ca -config myCA.cnf -gencrl -out crl/myCA.crl
We can read from this new CRL file.
openssl crl -in crl/myCA.crl -noout -text  

Inside of the CRL file, we will see our certificate revoked.
We can verify our CRL file.
openssl crl -in crl/myCA.crl -CAfile certs/myCA.crt -verify
# scp crl/myCa.crl webserver:/var/www/html/myCa.crlWe must copy the CRL file onto web server for download.

Because we created CRL file twice, the number in the "crlnumber.txt" file is 2732.

Leave a Comment

Your email address will not be published. Required fields are marked *