Table of Contents
Authenticity of a certificate is verified by signing from a Certificate Authority. We will be using CA cert and CA key for signing a Certificate Signing Request provided by the client. It is not recommended to sign a certificate directly with root CA, rather than use intermediate CA. This is because, if RootCA is compromised, it will be difficult to revoke a RootCA. In this article we will see how to create a RootCA and we will be using that RootCA to create an intermediate CA.
Create Root CA
Create directory structure for Root CA
We will be creating a directory structure in the parent directory ca
[root@3-vcp int]# mkdir ca;cd ca [root@3-vcp ca]# mkdir certs crl newcerts pvt_key [root@3-vcp ca]# ll total 16 drwxr-xr-x. 2 root root 4096 Aug 9 12:15 certs drwxr-xr-x. 2 root root 4096 Aug 9 12:15 crl drwxr-xr-x. 2 root root 4096 Aug 9 12:15 newcerts drwxr-xr-x. 2 root root 4096 Aug 9 12:15 pvt_key
Creating data base for issued certificates
We will be creating a flat file called serial and a file called index.txt. The serial file contain the next available serial number in Hex. Index.txt will have the details on the issued certificates
[root@3-vcp ca]# touch index.txt [root@3-vcp ca]# echo 00 > serial [root@3-vcp ca]# ll total 20 drwxr-xr-x. 2 root root 4096 Aug 9 12:15 certs drwxr-xr-x. 2 root root 4096 Aug 9 12:15 crl -rw-r--r--. 1 root root 0 Aug 9 12:34 index.txt drwxr-xr-x. 2 root root 4096 Aug 9 12:15 newcerts drwxr-xr-x. 2 root root 4096 Aug 9 12:15 pvt_key -rw-r--r--. 1 root root 3 Aug 9 12:34 serial
openssl conf file preparation
We must prepare an openssl configuration file for us to use. Below code snippet shows the configuration file used for this article. Explanations for the section of interest is given below code snippet
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations
dir = /root/int/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/pvt_key/.rand
# The root key and root certificate.
private_key = $dir/pvt_key/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_ca
[ policy_ca ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_int ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = default
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationalUnitName = Organizational Unit Name (eg, section)
0.organizationName = Organization Name (eg, company)
commonName = Common Name (eg, YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 40
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
- we will have to specify [ ca ], section to pick the options available from [ CA_default ]. This can be seen in the below code snippet.
- We will have to update the directory path in the section under [ CA_default ], with the path we have created
[ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations dir = /root/int/ca certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/pvt_key/.rand # The root key and root certificate. private_key = $dir/pvt_key/ca.key.pem certificate = $dir/certs/ca.cert.pem # For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 name_opt = ca_default cert_opt = ca_default default_days = 375 preserve = no policy = policy_ca
- we will be providing a separate policy for ca and intermediate ca
- For CA , we will be providing [ policy_ca ], for intermediate CA, we will be providing [ policy_int ]
- In the below code snippet, it can be seen phrases match, optional, supplied
- If the value is "match" then the field value must match the same field in the CA certificate.
- If the value is "supplied" then it must be present, but value need not to be same as CA
- If the value is "optional" then it may/maynot be present.
[ policy_ca ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_int ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional
- Parameter mentioned in the [ req ] sections are applied when creating CSR or Certificates
[ req ] # Options for the `req` tool (`man req`). default_bits = 4096 distinguished_name = req_distinguished_name string_mask = default # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca
- The value given in the field "distinguished name" need to be declared. This section contains the infomration which is required for creating a new Ceritifacte signing request (CSR)
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationalUnitName = Organizational Unit Name (eg, section)
0.organizationName = Organization Name (eg, company)
commonName = Common Name (eg, YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 40
- The fields [ v3_ca ] and [ v3_intermediate_ca ] , will be used as extension parameter for creating root and intermediate certificate
[ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign
Create Private key for RootCA
- We will be creating a private key for with 4096 bits size and we will be using 3des encryption
- It is necessary to ensure, we use protect the key with password, hence using 3des encryption and AES 256 encryption
[root@3-vcp ca]# openssl genrsa -aes256 -out pvt_key/ca.key.pem 4096 Generating RSA private key, 4096 bit long modulus ...............++ ..............................................................................++ e is 65537 (0x10001) Enter pass phrase for pvt_key/ca.key.pem: Verifying - Enter pass phrase for pvt_key/ca.key.pem: [root@3-vcp ca]#
Create Root CA Certificate
- Certificate can be created by req utility in openssl
- For creating Root CA certificate, we will be mentioning the custom openssl config file.
[root@3-vcp ca]# openssl req -config openssl.cnf -key pvt_key/ca.key.pem -new -x509 -days 10000 -sha256 -extensions v3_ca -out certs/ca.cert.pem Enter pass phrase for pvt_key/ca.key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:IN State or Province Name (full name) []:Karnataka Locality Name (eg, city) []:Bangalore Organizational Unit Name (eg, section) []:LinuxDataHub_CA Organization Name (eg, company) []:LinuxDataHub Common Name (eg, YOUR name) []:linuxdatahub_ca_cert Email Address []:[email protected]
Verify the Root CA
We can verify the Certificate to check the signature algorithm, validity, Issuer etc. Below code snippet shows the same
[root@3-vcp ca]# openssl x509 -noout -text -in certs/ca.cert.pem Certificate: Data: Version: 3 (0x2) Serial Number: b9:98:38:94:0c:bd:1d:ba Signature Algorithm: sha256WithRSAEncryption Issuer: C=IN, ST=Karnataka, L=Bangalore, OU=LinuxDataHub_CA, O=LinuxDataHub, CN=linuxdatahub_ca_cert/[email protected] Validity Not Before: Aug 9 14:26:44 2022 GMT Not After : Dec 25 14:26:44 2049 GMT Subject: C=IN, ST=Karnataka, L=Bangalore, OU=LinuxDataHub_CA, O=LinuxDataHub, CN=linuxdatahub_ca_cert/[email protected] Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 7E:B0:9C:31:D7:A9:A7:10:52:14:51:97:1E:52:13:1D:04:73:4F:3C X509v3 Authority Key Identifier: keyid:7E:B0:9C:31:D7:A9:A7:10:52:14:51:97:1E:52:13:1D:04:73:4F:3C X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption
It can be seen that in the X509v3 extensions, we can see the fields from the option [ v3_ca ] given in the openssl.conf file
Create Intermediate Certificates
Create directory structure for Intermediate Certificates
We will creating a directory structure for holding the files related to Intermediate cert generation
[root@3-vcp ca]# mkdir intermediate;cd intermediate [root@3-vcp intermediate]# mkdir certs crl csr newcerts pvt_key [root@3-vcp intermediate]# ll total 20 drwxr-xr-x. 2 root root 4096 Aug 9 18:50 certs drwxr-xr-x. 2 root root 4096 Aug 9 18:50 crl drwxr-xr-x. 2 root root 4096 Aug 9 18:50 csr drwxr-xr-x. 2 root root 4096 Aug 9 18:50 newcerts drwxr-xr-x. 2 root root 4096 Aug 9 18:50 pvt_key
Creating data base for Intermediate certs
We will be creating a flat files called serial and crlnumber and a file called index.txt. The serial file contain the next available serial number in hex. Index.txt will have the details on the issued certificates. crlnumber file is used to keep track of the revoked certificates.
[root@3-vcp intermediate]# pwd /root/int/ca/intermediate [root@3-vcp intermediate]# touch index.txt [root@3-vcp intermediate]# echo 00 > serial [root@3-vcp intermediate]# echo 01 > crl/crlnumber
Creating Openssl configuration
We will be reusing the openssl configuration file which we have used, But with small modification
[ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations dir = /root/int/ca/intermediate certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/pvt_key/.rand # The root key and root certificate. private_key = $dir/pvt_key/inter_ca.key.pem certificate = $dir/certs/inter_ca.cert.pem # For certificate revocation lists. crlnumber = $dir/crl/crlnumber policy = policy_int
Create Private key for Intermediate CA
- We will be creating an intermediate private key for with 4096 bits size and we will be using 3des encryption
[root@3-vcp intermediate]# openssl genrsa -aes256 -out pvt_key/intermediate.key 4096 Generating RSA private key, 4096 bit long modulus ....................................++ ...++ e is 65537 (0x10001) Enter pass phrase for pvt_key/intermediate.key: Verifying - Enter pass phrase for pvt_key/intermediate.key: [root@3-vcp intermediate]#
Create CSR for Intermediate CA
We will create a CSR using the private key which we have generated in the above step. It should be noted that the Common Name of the CSR should be different from the Root CA
[root@3-vcp intermediate]# openssl req -config openssl.cnf -new -sha256 -key pvt_key/intermediate.key -out csr/ntermediate.csr Enter pass phrase for pvt_key/intermediate.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:IN State or Province Name (full name) []:Karnataka Locality Name (eg, city) []:Bangalore Organizational Unit Name (eg, section) []:LDH-Banglore Organization Name (eg, company) []:LinuxDataHub Common Name (eg, YOUR name) []:LDH-Banglore-int-ca Email Address []:[email protected] [root@3-vcp intermediate]#
[root@3-vcp intermediate]#openssl ca -config /root/int/ca/openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in csr/ntermediate.csr -out int.ca
Using configuration from /root/int/ca/openssl.cnf
Enter pass phrase for /root/int/ca/pvt_key/ca.key.pem:
Check that the request matches the signature
Signature ok
The countryName field needed to be the same in the
CA certificate (IN) and the request (US)
Create Intermediate CA certificate.
- We will be using the Root CA to sign the intermediate CSR.
- Below code snippet shows the signing process, we will be using the v3_intermediate_ca extension
[root@3-vcp intermediate]# openssl ca -config /root/int/ca/openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in csr/ntermediate.csr -out certs/int.ca Using configuration from /root/int/ca/openssl.cnf Enter pass phrase for /root/int/ca/pvt_key/ca.key.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 0 (0x0) Validity Not Before: Aug 9 14:32:20 2022 GMT Not After : Aug 6 14:32:20 2032 GMT Subject: countryName = IN stateOrProvinceName = Karnataka organizationName = LinuxDataHub organizationalUnitName = LDH-Banglore commonName = LDH-Banglore-int-ca emailAddress = [email protected] X509v3 extensions: X509v3 Subject Key Identifier: 54:D1:6D:89:6D:22:9A:39:0C:F0:65:29:30:9E:5B:D9:50:DF:EB:C1 X509v3 Authority Key Identifier: keyid:7E:B0:9C:31:D7:A9:A7:10:52:14:51:97:1E:52:13:1D:04:73:4F:3C X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Certificate is to be certified until Aug 6 14:32:20 2032 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
- Since we have signed the intermediate CSR with RootCA, the index file belonging to RootCA will have the details. The Database file have been mentioned on the openssl conf file
[root@3-vcp ca]# cat index.txt V 320806143220Z 00 unknown /C=IN/ST=Karnataka/O=LinuxDataHub/OU=LDH-Banglore/CN=LDH-Banglore-int-ca/[email protected]
Verify the Intermediate Certificate
- We can list the content of the Intermediate certificate to view the issuer, expiry and other details for the certificates.
[root@3-vcp newcerts]# openssl x509 -noout -text -in int.ca Certificate: Data: Version: 3 (0x2) Serial Number: 0 (0x0) Signature Algorithm: sha256WithRSAEncryption Issuer: C=IN, ST=Karnataka, L=Bangalore, OU=LinuxDataHub_CA, O=LinuxDataHub, CN=linuxdatahub_ca_cert/[email protected] Validity Not Before: Aug 9 14:32:20 2022 GMT Not After : Aug 6 14:32:20 2032 GMT Subject: C=IN, ST=Karnataka, O=LinuxDataHub, OU=LDH-Banglore, CN=LDH-Banglore-int-ca/[email protected] Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 54:D1:6D:89:6D:22:9A:39:0C:F0:65:29:30:9E:5B:D9:50:DF:EB:C1 X509v3 Authority Key Identifier: keyid:7E:B0:9C:31:D7:A9:A7:10:52:14:51:97:1E:52:13:1D:04:73:4F:3C X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption
[root@3-vcp newcerts]# ls -l /root/int/ca/newcerts
total 4
-rw-r--r--. 1 root root 2187 Aug 9 20:02 00.pem
- We can verify the intermediate certificate validity by checking against the Root CA
[root@3-vcp newcerts]# openssl verify -CAfile ../certs/ca.cert.pem int.ca int.ca: OK
Create Certificate Bundle.
For an application to verify the authenticity of a certificate, it need to verify the signing authority of signing CA. If we use an intermediate CA as the signing authority. The application need to verify the validity of the intermediate CA. For that we need to provide the Root CA also to the application. We will have to create a certificate bundle which contains the RootCA and the intermediate CA , for the application to verify.
For creating a certificate bundle, we need to concatenate the RootCA and intermediate CA to one file
[root@3-vcp intermediate]# cat ../certs/ca.cert.pem certs/int.ca > cert-bundle.pem
Verify Certificate Bundle
Openssl certificate chain can be verified against RootCA using the below command
[root@3-vcp intermediate]# openssl verify -CAfile ../certs/ca.cert.pem cert-bundle.pem cert-bundle.pem: OK
Practical Example of the certificate chains
Below pic shows the certificate bundle of our website linuxdatahub.com provided by the CA providers
References
Directory structure
Below is the complete directory structure after the exercise of creating RootCA and intermediate CA
[root@3-vcp int]# tree . . └── ca ├── certs │ └── ca.cert.pem ├── crl ├── index.txt ├── index.txt.attr ├── index.txt.old ├── intermediate │ ├── cert-bundle.pem │ ├── certs │ │ ├── int.ca │ │ └── int.ca.crt │ ├── crl │ │ └── crlnumber │ ├── csr │ │ └── ntermediate.csr │ ├── index.txt │ ├── newcerts │ ├── openssl.cnf │ ├── pvt_key │ │ └── intermediate.key │ └── serial ├── newcerts │ └── 00.pem ├── openssl.cnf ├── pvt_key │ └── ca.key.pem ├── serial └── serial.old 11 directories, 18 files
Thank you very much for your info! It really worked.
Thank you very much