Your own Certificate Authority


banner

As mentioned in the previous article, there are some scenarios that it would be useful to run your own Certificate Authority (CA). For example:

  • When you require a lot of certificates.
  • Authenticate users or client devices.

It is possible to run your own mini Certificate Authority manually.

To request an SSL certificate from a CA like Verisign or GoDaddy, you send them a Certificate Signing Request (CSR), and they give you an SSL certificate in return that they have signed using their root certificate and private key. All browsers have a copy (or access to a copy from the operating system) of the root certificate from the various CAs, so the browser can verify that your certificate was signed by a trusted CA.

That’s why when you generate a self-signed certificate the browser doesn’t trust it. It hasn’t been signed by a CA. The way to get around this is to generate our own root certificate and private key. We then add the root certificate to all the devices we own just once, and then all the certificates we generate will be inherently trusted.

This tutorial uses OpenSSL. OpenSSL is a free and open-source cryptographic library that provides several command-line tools for handling digital certificates. Some of these tools can be used to act as a certificate authority.

Generating root cert

Acting as a certificate authority (CA) means dealing with cryptographic pairs of private keys and public certificates. The very first cryptographic pair we’ll create is the root pair. This consists of the root key (ca.key.pem) and root certificate (ca.cert.pem). This pair forms the identity of your CA.

Typically, the root CA does not sign server or client certificates directly. The root CA is only ever used to create one or more intermediate CAs, which are trusted by the root CA to sign certificates on their behalf. This is best practice. It allows the root key to be kept offline and unused as much as possible, as any compromise of the root key is disastrous.

Note

It’s best practice to create the root pair in a secure environment. Ideally, this should be on a fully encrypted, air gapped computer that is permanently isolated from the Internet. Remove the wireless card and fill the ethernet port with glue.

Preparation

Choose a directory (/home/root-ca) to store all keys and certificates.

# mkdir /home/root-ca

Create the directory structure. The index.txt and serial files act as a flat file database to keep track of signed certificates.

# cd /home/root-ca
# mkdir certs csr crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial

You must create a configuration file for OpenSSL to use in /home/root-ca/openssl.cnf

# OpenSSL root CA configuration file.
# Copy to `/home/root-ca/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/root-ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/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_strict

[ policy_strict ]
# 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_loose ]
# 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        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# 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 ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
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

# Optionally, specify some defaults.
countryName_default             = NL
# stateOrProvinceName_default   = 
localityName_default            = Den Haag
# 0.organizationName_default      = Alice Ltd
# organizationalUnitName_default  =
emailAddress_default            =

[ 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

The [ ca ] section is mandatory. Here we tell OpenSSL to use the options from the [ CA_default ] section.

The [ CA_default ] section contains a range of defaults. Make sure you declare the directory you chose earlier (/home/ca).

We’ll apply policy_strict for all root CA signatures, as the root CA is only being used to create intermediate CAs.

We’ll apply policy_loose for all intermediate CA signatures, as the intermediate CA is signing server and client certificates that may come from a variety of third-parties.

Options from the [ req ] section are applied when creating certificates or certificate signing requests.

The [ req_distinguished_name ] section declares the information normally required in a certificate signing request. You can optionally specify some defaults.

The next few sections are extensions that can be applied when signing certificates. For example, passing the -extensions v3_ca command-line argument will apply the options set in [ v3_ca ].

We’ll apply the v3_ca extension when we create the root certificate.

We’ll apply the v3_ca_intermediate extension when we create the intermediate certificate. pathlen:0 ensures that there can be no further certificate authorities below the intermediate CA.

We’ll apply the usr_cert extension when signing client certificates, such as those used for remote user authentication.

We’ll apply the server_cert extension when signing server certificates, such as those used for web servers.

Creating the root key

Create the root key (ca.key.pem) and keep it absolutely secure. Anyone in possession of the root key can issue trusted certificates. Encrypt the root key with AES 256-bit encryption and a strong password.

Note

Use 4096 bits for all root and intermediate certificate authority keys. You’ll still be able to sign server and client certificates of a shorter length.

# cd /home/root-ca
# openssl genrsa -aes256 -passout pass:secretpassword -out private/ca.key.pem 4096
# chmod 400 private/ca.key.pem

Creating the root certificate

Use the root key (ca.key.pem) to create a root certificate (ca.cert.pem). Give the root certificate a long expiry date, such as twenty years. Once the root certificate expires, all certificates signed by the CA become invalid.

Warning

Whenever you use the req tool, you must specify a configuration file to use with the -config option, otherwise OpenSSL will default to /etc/pki/tls/openssl.cnf.

# cd /root/root-ca
# openssl req -config openssl.cnf \
      -passin pass:secretpassword \
      -key private/ca.key.pem \
      -new -x509 -days 7300 -sha256 -extensions v3_ca \
      -out certs/ca.cert.pem \
      -subj "/C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Root CA"
# chmod 444 certs/ca.cert.pem

To verify the root certificate do:

# openssl x509 -noout -text -in certs/ca.cert.pem

The output shows:

  • the Signature Algorithm used
  • the dates of certificate Validity
  • the Public-Key bit length
  • the Issuer, which is the entity that signed the certificate
  • the Subject, which refers to the certificate itself

The Issuer and Subject are identical as the certificate is self-signed. Note that all root certificates are self-signed.

        Issuer: C=NL, ST=ZH, O=Alice Ltd, CN=Alice Ltd Root CA
        Validity
            Not Before: May  8 22:29:26 2025 GMT
            Not After : May  3 22:29:26 2045 GMT
        Subject: C=NL, ST=ZH, O=Alice Ltd, CN=Alice Ltd Root CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)

The output also shows the X509v3 extensions. We applied the v3_ca extension, so the options from [ v3_ca ] should be reflected in the output.

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                64:2B:BA:1A:12:9F:D2:B6:62:45:1D:EC:07:17:DC:DB:CA:E8:E9:A5
            X509v3 Authority Key Identifier: 
                64:2B:BA:1A:12:9F:D2:B6:62:45:1D:EC:07:17:DC:DB:CA:E8:E9:A5
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign

Minimalistic Root certificate

Alternatively you can take the minimalistic approach:

  1. Create certificate directory
    mkdir ~/ca
    cd ~/ca
  2. Generate the private key:
    openssl genrsa -des3 -passout pass:secretpassword -out myCA.key 4096
  3. Generate root certificate:
    openssl req -x509 -new -nodes -passin pass:secretpassword -key myCA.key \
         -sha256 -days 1825 -out myCA.pem \
         -subj "/C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Root CA"
  4. Verify certificate:
    openssl x509 -noout -text -in myCA.pem

    You can skip the intermediat certificate steps.

Create intermediate cert

An intermediate certificate authority (CA) is an entity that can sign certificates on behalf of the root CA. The root CA signs the intermediate certificate, forming a chain of trust.

The purpose of using an intermediate CA is primarily for security. The root key can be kept offline and used as infrequently as possible. If the intermediate key is compromised, the root CA can revoke the intermediate certificate and create a new intermediate cryptographic pair.

Prepare the directory

The root CA files are kept in /home/root-ca. Choose a different directory (/home/int-ca) to store the intermediate CA files.

# mkdir /home/int-ca

Create the same directory structure used for the root CA files. It’s convenient to also create a csr directory to hold certificate signing requests.

# cd /home/int-ca
# mkdir certs crl csr newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial

Add a crlnumber file to the intermediate CA directory tree. crlnumber is used to keep track of certificate revocation lists.

# echo 1000 > crlnumber

Create a file in /home/int-ca/openssl.cnf:

# OpenSSL intermediate CA configuration file.
# Copy to `/home/int-ca/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/int-ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/intermediate.key.pem
certificate       = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/intermediate.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_loose

[ policy_strict ]
# 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_loose ]
# 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        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# 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 ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
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

# Optionally, specify some defaults.
countryName_default             = NL
# stateOrProvinceName_default   = 
localityName_default            = Den Haag
# 0.organizationName_default      = Alice Ltd
# organizationalUnitName_default  =
emailAddress_default            =

[ 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

Five options have changed compared to the root CA configuration file:

[ CA_default ]
dir             = /home/int-ca
private_key     = $dir/private/intermediate.key.pem
certificate     = $dir/certs/intermediate.cert.pem
crl             = $dir/crl/intermediate.crl.pem
policy          = policy_loose

Create the intermediate key

Create the intermediate key (intermediate.key.pem). Encrypt the intermediate key with AES 256-bit encryption and a strong password.

This is done in the intermediate CA

# cd /home/int-ca
# openssl genrsa -aes256 \
      -passout pass:secretpassword \
      -out private/intermediate.key.pem 4096
# chmod 400 private/intermediate.key.pem

Create the intermediate certificate

Use the intermediate key to create a certificate signing request (CSR). The details should generally match the root CA. The Common Name, however, must be different.

Warning

Make sure you specify the intermediate CA configuration file (/home/int-ca/openssl.cnf).

# cd /home/int-ca
# openssl req -config openssl.cnf -new -sha256 \
      -passin pass:secretpassword \
      -key private/intermediate.key.pem \
      -out csr/intermediate.csr.pem \
      -subj "/C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Intermediate CA"

To create an intermediate certificate, use the root CA with the v3_intermediate_ca extension to sign the intermediate CSR. The intermediate certificate should be valid for a shorter period than the root certificate. Ten years would be reasonable.

Copy the intermeida certificates csr to the root CA. If you follow hard security practices you may need to manually copy the csr file to the air-gapped root CA system. In our example, we simply copy:

# cp -av /home/int-ca/csr/intermediate.csr.pem /home/root-ca/csr

Warning

This time, specify the root CA configuration file (/home/root-ca/openssl.cnf).

# cd /home/root-ca
# openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
      -days 3650 -notext -md sha256 \
      -passin pass:secretpassword \
      -in csr/intermediate.csr.pem \
      -out certs/intermediate.cert.pem

Sign the certificate? [y/n]: y
1 out of 1 certificate requests certified, commit? [y/n]y

# chmod 444 certs/intermediate.cert.pem

The index.txt file is where the OpenSSL ca tool stores the certificate database. Do not delete or edit this file by hand. It should now contain a line that refers to the intermediate certificate.

V   350506223334Z       1000    unknown /C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Intermediate CA

Verify the intermediate certificate

As we did for the root certificate, check that the details of the intermediate certificate are correct.

# openssl x509 -noout -text \
      -in certs/intermediate.cert.pem

Verify the intermediate certificate against the root certificate. An OK indicates that the chain of trust is intact.

# openssl verify -CAfile certs/ca.cert.pem \
      certs/intermediate.cert.pem

intermediate.cert.pem: OK

Create the certificate chain file

When an application (eg, a web browser) tries to verify a certificate signed by the intermediate CA, it must also verify the intermediate certificate against the root certificate. To complete the chain of trust, create a CA certificate chain to present to the application.

To create the CA certificate chain, concatenate the intermediate and root certificates together. We will use this file later to verify certificates signed by the intermediate CA.

# cat certs/intermediate.cert.pem \
      certs/ca.cert.pem > certs/intermediate-full-chain.cert.pem
# chmod 444 certs/intermediate-full-chain.cert.pem

Note

Our certificate chain file must include the root certificate because no client application knows about it yet. A better option, particularly if you’re administrating an intranet, is to install your root certificate on every client that needs to connect. In that case, the chain file need only contain your intermediate certificate.

At this point you need to copy from the root CA to the intermediate CA the files:

  • certs/intermediate.cert.pem
  • certs/intermediate-full-chain.cert.pem
cp -av /home/root-ca/certs/intermediate*.pem /home/int-ca/certs

Minimalistic Approach

For the minimalistic approach, this entire section can be skipped.

Signing client/server certificates

We will be signing certificates using our intermediate CA. You can use these signed certificates in a variety of situations, such as to secure connections to a web server or to authenticate clients connecting to a service.

Note

The steps below are from your perspective as the certificate authority. A third-party, however, can instead create their own private key and certificate signing request (CSR) without revealing their private key to you. They give you their CSR, and you give back a signed certificate. In that scenario, skip the genrsa and req commands.

Create a key

Our root and intermediate pairs are 4096 bits. Server and client certificates normally expire after one year, so we can safely use 2048 bits instead.

Note

Although 4096 bits is slightly more secure than 2048 bits, it slows down TLS handshakes and significantly increases processor load during handshakes. For this reason, most websites use 2048-bit pairs.

If you’re creating a cryptographic pair for use with a web server (eg, Apache), you probably want to create a key without a password so that you don't need to enter the password every time you restart the web server:

# cd /home/int-ca
# openssl genrsa  \
      -out private/www.example.com.key.pem 2048
# chmod 400 private/www.example.com.key.pem

On the other hand, if you are creating a key for an interactive user, creating a key with password would be beneficial:

# cd /home/int-ca
# openssl genrsa  \
      -aes256 \
      -passout pass:secretpassword \
      -out private/user.alice.key.pem 2048
# chmod 400 private/user.alice.key.pem

Create a certificate

Use the private key to create a certificate signing request (CSR). The CSR details don’t need to match the intermediate CA. For server certificates, the Common Name must be a fully qualified domain name (eg, www.example.com), whereas for client certificates it can be any unique identifier (eg, an e-mail address). Note that the Common Name cannot be the same as either your root or intermediate certificate.

# cd /home/int-ca
# openssl req -config openssl.cnf \
      -key private/www.example.com.key.pem \
      -new -sha256 -out csr/www.example.com.csr.pem \
      -subj "/C=NL/CN=www.example.com"

For the user case you may use:

# cd /home/int-ca
# openssl req -config openssl.cnf \
      -passin pass:secretpassword \
      -key private/user.alice.key.pem \
      -new -sha256 -out csr/user.alice.csr.pem \
      -subj "/C=NL/CN=user.alice/[email protected]"

To create a certificate, use the intermediate CA to sign the CSR. If the certificate is going to be used on a server, use the server_cert extension. If the certificate is going to be used for user authentication, use the usr_cert extension. Certificates are usually given a validity of one year, though a CA will typically give a few days extra for convenience.

# cd /home/int-ca
# openssl ca -config openssl.cnf \
      -passin pass:secretpassword \
      -extensions server_cert -days 375 -notext -md sha256 \
      -in csr/www.example.com.csr.pem \
      -out certs/www.example.com.cert.pem
# chmod 444 certs/www.example.com.cert.pem

The intermediate/index.txt file should contain a line referring to this new certificate.

V   350506223334Z       1000    unknown /C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Intermediate CA

For the user case you may use:

# cd /home/int-ca
# openssl ca -config openssl.cnf \
      -passin pass:secretpassword \
      -extensions usr_cert -days 375 -notext -md sha256 \
      -in csr/user.alice.csr.pem \
      -out certs/user.alice.cert.pem
# chmod 444 certs/user.alice.cert.pem

Verify the certificate

# openssl x509 -noout -text \
      -in certs/www.example.com.cert.pem

The Issuer is the intermediate CA. The Subject refers to the certificate itself.

        Issuer: C=NL, ST=ZH, O=Alice Ltd, CN=Alice Ltd Intermediate CA
        Validity
            Not Before: May  8 23:42:47 2025 GMT
            Not After : May 18 23:42:47 2026 GMT
        Subject: C=NL, CN=www.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

The output will also show the X509v3 extensions. When creating the certificate, you used either the server_cert or usr_cert extension. The options from the corresponding configuration section will be reflected in the output.

        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Cert Type: 
                SSL Server
            Netscape Comment: 
                OpenSSL Generated Server Certificate
            X509v3 Subject Key Identifier: 
                FA:B9:39:0C:09:67:53:20:D1:FC:2D:B9:00:05:91:98:4E:4D:B4:F0
            X509v3 Authority Key Identifier: 
                keyid:D9:13:85:BC:23:8A:24:BA:A0:D9:A2:21:C9:79:95:34:E3:85:E1:2A
                DirName:/C=NL/ST=ZH/O=Alice Ltd/CN=Alice Ltd Root CA
                serial:10:00
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication

Use the CA certificate chain file we created earlier (ca-chain.cert.pem) to verify that the new certificate has a valid chain of trust.

# openssl verify -CAfile certs/intermediate-full-chain.cert.pem \
      certs/www.example.com.cert.pem

www.example.com.cert.pem: OK

Deploy the certificate

You can now either deploy your new certificate to a server, or distribute the certificate to a client. When deploying to a server application (eg, Apache), you need to make the following files available:

intermediate-full-chain.cert.pem
www.example.com.key.pem
www.example.com.cert.pem

If you’re signing a CSR from a third-party, you don’t have access to their private key so you only need to give them back the chain file (ca-chain.cert.pem) and the certificate (www.example.com.cert.pem).

Minimal approach

  1. Create private key:
    openssl genrsa -out www.example.com.key 2048
  2. Generate CSR:
    openssl req -new \
             -key www.example.com.key \
             -out www.example.com.csr \
             -addext "subjectAltName = DNS:foo.co.uk, DNS:*.app.example.com" \
             -subj "/C=NL/CN=www.example.com"
  3. Create the certificate: using our CSR, the CA private key and the CA certificate:
    openssl x509 -req \
           -passin pass:secretpassword \
           -CA myCA.pem -CAkey myCA.key -CAcreateserial \
           -days 825 -sha256 \
           -copy_extensions copyall \
           -in www.example.com.csr \
           -out www.example.com.crt

We now have three files: www.example.com.key (the private key), www.example.com.csr (the certificate signing request, or csr file), and www.example.com.crt (the signed certificate). We can configure local web servers to use HTTPS with the private key and the signed certificate.

Conclusion

This articles covers two approaches for running Certificate Authorities only using openssl commands.

The full approach can be implementely quite securely and explicitly support server and client certificates.

The minimal approach is quite straight forward for a quick and dirty solution.

References