How to set up Private CA and use the certificates issued by Private CA ?

Amod Kadam
7 min readFeb 3, 2023
Private CA , Root Certificate and Server Certificate

In this post we will look at

  • How to create a Private CA ?
  • Issue server certificate signed by Private CA
  • Configure Server Certificate on the web server (e.g. nginx server )
  • Verify the working

Note : The approach and steps discussed here are suitable for the development environment and not recommended for the Production environment.

What is Private CA ?

A Private Certificate Authority (CA) is a type of CA that is used to issue digital certificates for internal use within an organization. Private CA’s are typically used for internal applications such as VPNs, internal websites, or for issuing client certificates to secure internal communications.Private CA’s are typically self-signed or signed by a root CA within the organization.

Step 1 — Create Private CA

Note : The instructions and commands are executed on MacOS. However the equivalent steps should work with Linux or Windows OS.

Creating Private CA simply requires couple of commands.

  1. Generate private key
openssl genrsa -des3 -out cloudmanthanCA.key 2048

The options used in the command are:

- genrsa: generate a RSA private key

-des3: encrypt the private key using Triple DES (3DES) encryption

-out cloudmanthanCA.key: The private key will be stored in a file named cloudmanthanCA.key

2048: The RSA key size of 2048 bits is commonly used for generating private keys

Enter pass phrase as an extra layer of protection

We will refer to this key as root key of the Private CA.

2. Generate root certificate with private key created earlier

openssl req -x509 -new -nodes -key cloudmanthanCA.key -sha256 -days 1825 -out cloudmanthanCA.pem

req: This option tells OpenSSL to process a certificate request

-x509: generate a self-signed X.509 certificate

-new: create a new certificate request

-nodes: (Read as NO DES) not to encrypt the private key of the certificate

-key cloudmanthanCA.key: private key to use for signing the certificate

-sha256: use the SHA-256 message digest algorithm for signing the certificate

-days 1825: the number of days for which the certificate will be valid. The certificate will be valid for 1825 days (roughly 5 years).

-out cloudmanthanCA.pem: the output file name for the certificate. The certificate will be stored in a file named cloudmanthanCA.pem

Creating Root Certificate of Private CA

That is all required to have a Private CA !

Step 2 — Issue server certificate using the Private CA

  1. Geneate the private key for server

The key name could be anything but having some pattern or naming convention is recommended in the real world.

openssl genrsa -out dev.cloudmanthan.key 2048

2. Generate Certificate Signing Request (CSR) using the above private key

openssl req -new -key dev.cloudmanthan.key -out dev.cloudmanthan.csr
Creating CSR for Server

3. Create certificate with Subject Alternative Name (SAN)

  • SAN Certificates allow you to secure a primary domain and then add additional domains to the Subject Alternative Name field of the certificate
  • SAN enables to use the single certificate with multiple DNS names
  • On Goggle Chrome, Version 58, all SSL Certificates must include a SAN as the common name is ignored and SAN entries are used instead

Create a file with name dev.cloudmanthan.ext

# dev.cloudmanthan.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = dev.cloudmanthan.internal
openssl x509 -req -in dev.cloudmanthan.csr -CA cloudmanthanCA.pem -CAkey cloudmanthanCA.key -CAcreateserial -out dev.cloudmanthan.crt -days 825 -sha256 -extfile dev.cloudmanthan.ext

The various options in the command are :

x509: process an X.509 certificate request

-req: input is a certificate request

-in dev.cloudmanthan.csr: specifies the input file for the certificate request

-CA cloudmanthanCA.pem: specifies the CA certificate to use for signing the certificate request. The CA certificate is stored in a file named cloudmanthanCA.pem

-CAkey cloudmanthanCA.key: specifies the private key of the CA to use for signing the certificate request. The private key is stored in a file named cloudmanthanCA.key

-CAcreateserial: Create a serial number file for the CA if it doesn’t already exist

-out dev.cloudmanthan.crt: specifies the output file name for the signed certificate. The signed certificate will be stored in a file named dev.cloudmanthan.crt

-days 825: specifies the number of days for which the certificate will be valid. The certificate will be valid for 825 days (roughly 2 years).

-sha256: Use the SHA-256 message digest algorithm for signing the certificate

-extfile dev.cloudmanthan.ext: specifies an additional file containing X.509 extensions to be included in the certificate. The extension file is stored in a file named dev.cloudmanthan.ext.

Create Server Certificate

Thus we have a server certificate issued by our Private CA!

Step 3 — Verify that server certificate (optional)

openssl x509 -text -noout -in dev.cloudmanthan.crt
Certificate Issuer
SAN in Server Certificate

SAN Present on the Server Certificate.

Great .. ! so now you have server certificate signed by your private CA.

Step 4 — Configure Certificate on the nginx server

Note: nginx server is installed on my Mac already

  1. Edit the file nginx.conf
vi /usr/local/etc/nginx/nginx.conf

You need to provide the path for ssl_certificate and ssl_certificate_key

Nginx SSL Configuration

2. Reload nginx service

nginx -s reload

Step 5 — Verify the working

  1. Open chrome browser and go to https://locahost
Certificate Authority Invalid Error

If you check the certificate you should see the certificate dev.cloudmanthan.internal is issued by our private CA — www.cloudmanthan.internal.

Server Certificate issued by Private CA

However it shows an error : ERR_CERT_AUTHORITY_INVALID.

Unlike public CA’s, private CA’s are not publicly trusted and their certificates are not included in web browsers or operating systems by default.

2. Add the Private CA to trust store on MacOS

sudo security add-trusted-cert -d -r trustRoot -k “/Library/Keychains/System.keychain” cloudmanthanCA.pem

add-trusted-cert: tells the security command to add a trusted certificate

-d: certificate should be added to the System keychain, rather than the user’s keychain

-r trustRoot: specifies the trust setting for the certificate, in this case the trust root setting

-k “/Library/Keychains/System.keychain”: specifies the keychain to which the certificate should be added. In this case, the System keychain is specified.

cloudmanthanCA.pem: This is the name of the certificate file to be added to the keychain. The file cloudmanthanCA.pem contains the CA certificate that is being added as a trusted root certificate.

As this is a privileged action you will be asked to provide the password of the administrative user.

Adding Private CA certificate to the trust store on MacOS

Once added you should see that your Private CA certificate in the System Roots trust store.

3. If you refresh the browser page earlier error is gone but now you get ERR_CERT_COMMON_NAME_INVALID

Error : Common Name Invalid

This is happening because localhost does not exist in the server certificate as the server certificate is issued to dev.cloudmanthan.internal

4. Let us modify the /etc/hosts file to add the hostname dev.cloudmanthan.internal and map it to 127.0.0.1 (localhost)

sudo vi /etc/hosts
dev.cloudmanthan.internal name mapped to 127.0.0.1

5. Go to the url dev.cloudmanthan.internal and you should see the default nginx page !

Root CA now trusted by browser

Henceforth any new certificates issued by www.cloudmanthan.internal i.e your Private CA will be automatically trusted by your browser. Try creating the certificate for test.cloudmanthan.internal and configure it with nginx and see how it goes !

Summary

In this post we have

  • Created Private CA
  • Created server certificate signed by Private CA
  • Configured the certificate on the server
  • Added Private CA certificate to the trust store so that the browser trusts the certificates

This approach is really handy for development purpose where you want to test the application with https turned on.

The use of a private CA provides organizations with more control and flexibility over their certificate infrastructure, as they can issue and manage their own certificates and configure them according to their specific needs. However, it also increases the responsibility of the organization to properly manage the private CA and ensure its security, as a compromise of the private CA can lead to a wider security breach. This is absolutely key for running a Private CA for Production Grade environment. !

https://buymeacoffee.com/amodkadam

--

--

Amod Kadam

AWS Community Builder | upGrad Course Author | 7 x AWS | Terraform Associate | Cloud Consulting | AWS | Azure | Docker | Kubernetes | Software Architecture