Cookie consent

This website uses cookies to personalise content and to analyse traffic.

Basic (mandatory) - Cookies needed to store user preferences.
Marketing (optional) - Marketing cookies are used to track users activity and to provide them with personalized advertisements.

You can learn about cookies on our Privacy Policy page.
Cookie settings can be changed at any time by clicking the icon located at the beginning of the navigation bar at the top of the page.

LINUX
  ADMIN
    SMART
      GUIDE

Generating server and user certificates

Outline
  1. Creating a server certificate
  2. Creating a user certificate
  3. Generating certificates based on elliptic curve P-256

The generation of client (servers and users) certificates is similar to the one seen for CA certificate creation. It is assumed that the reader already owns a CA certificate (see Generating a CA Root Certificate).

Creating a server certificate

Suppose that we are setting up a server to provide both web and email access to users of our company. For this reason, the names www.mycompany.com and mail.mycompany.com were already configured in the company DNS and resolved to the IP address of the server. Then, we want to create a certificate to certify the identity of the server towards when a generic user of our company attempts to connect to the server. We obviusly took care of sharing our CA certificate to that users so as to allow them to verifiy everithing signed by our CA.

The first thing to do is to set some parameters in the openssl.cnf configuration file.


root@myhost:~# cd /etc/ssl
root@myhost:/etc/ssl# nano openssl.cnf

Go down to [ usr_cert ] block, comment out the part related to the user certificate and update the part related to the server certificate as highlighted in red in the following, then save and exit.


[ usr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

##### for SERVER certificate ######
nsCertType = server
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = DNS:www.mycompany.com, DNS:mail.mycompany.com

##### for USER certificate ######
#nsCertType = client, email
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
#extendedKeyUsage = clientAuth, emailProtection
#subjectAltName = email:mary.white@mycompany.com, email:mary@mycompany.com

Now we are ready to run the command for generating the certificate signing request.


root@myhost:/etc/ssl# cd reqs
root@myhost:/etc/ssl/reqs# openssl req -newkey rsa:4096 -noenc -keyout hostKey.pem -out hostReq.pem
.....+....+.....+.......+.....+...+......+.+...+..+............+.+..+.........+....+++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++*...........++++++++++++++++++++++++++++++++++++++++++++++++
...
lot of + and .
...
.+......+.+...+.........+........+...+.+........+......+......+.........+.+.....+...+..........+...+....
.....+...+.................+.+............+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-----
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) [US]:
State or Province Name (full name) [California]:
Locality Name (eg, city) [San Francisco]:
Organization Name (eg, company) [My Company]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.mycompany.com
Email Address [netadmin@mycompany.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Press Enter for confirming any default value and specify the common name that, for servers, is typically set to the most relevant DNS name.

If your linux distribution uses OpenSSL 1.1.* instead of OpenSSL 3.*.*, use -nodes in place of -noenc. As can be seen, we told openssl to not encrypt the private key. This is needed to make it possible a server reboot without human interacton; if the private key were encrypted, it should have been manually entered every time the server (or the daemon) is restarted. For safety reasons, is the crucial that the file hostKey.pem has permission mode 600.


root@myhost:/etc/ssl/reqs# ls -la
total 20
drwx------ 2 root root    4 Nov 17 14:44 .
drwxr-xr-x 9 root root   11 Nov 17 14:38 ..
-rw------- 1 root root 3272 Nov 17 14:44 hostKey.pem
-rw-r--r-- 1 root root 1756 Nov 17 14:44 hostReq.pem

Now we need to ask our CA to sign the certificate request.


root@myhost:/etc/ssl/reqs# openssl ca -in hostReq.pem -days 3650 -out hostCert.pem -notext
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/cakey.pem: TYPE_YOUR_SECRET
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Nov 17 14:35:26 2022 GMT
            Not After : Nov 14 14:35:26 2032 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = California
            organizationName          = My Company
            commonName                = www.mycompany.com
            emailAddress              = netadmin@mycompany.com
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Subject Key Identifier: 
                7F:A6:E0:22:D7:D4:78:03:71:DC:55:D2:04:BB:E9:4A:16:FA:5C:87
            X509v3 Authority Key Identifier: 
                00:32:A8:49:BC:A0:EF:26:DA:50:D0:A4:E6:1C:B0:17:58:57:F6:1F
            Netscape Cert Type: 
                SSL Server
            X509v3 Key Usage: 
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Subject Alternative Name: 
                DNS:www.mycompany.com, DNS:mail.mycompany.com
Certificate is to be certified until Nov 14 14:35:26 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

The server certificate is then ready. The last thing we have to do is to move the files in the appropriate directories, also giving them a easily recognizable name.


root@myhost:/etc/ssl/reqs# mv hostKey.pem ../private/wwwKey.pem
root@myhost:/etc/ssl/reqs# mv hostCert.pem ../mycerts/wwwCert.pem
root@myhost:/etc/ssl/reqs# mv hostReq.pem wwwReq.pem
root@myhost:/etc/ssl/reqs# chmod 600 wwwReq.pem

The last thing to do is to make the private key accessible by the daemons needing it. The best way to do that is to make it readable by the group ssl-cert. Then, the system user running the daemon will also have to be added to the same group.


root@myhost:/etc/ssl/reqs# cd /etc/ssl/private/
root@myhost:/etc/ssl/private# chgrp ssl-cert wwwKey.pem 
root@myhost:/etc/ssl/private# chmod 640 wwwKey.pem
root@myhost:/etc/ssl/private# ls -la
total 25
drwx--x--- 2 root ssl-cert    5 Nov 17 15:48 .
drwxr-xr-x 9 root root       15 Nov 17 15:35 ..
-rw------- 1 root root     3434 Nov 16 16:50 cakey.pem
-rw-r----- 1 root ssl-cert 1704 Apr 24  2022 ssl-cert-snakeoil.key
-rw-r----- 1 root ssl-cert 3272 Nov 17 14:44 wwwKey.pem

There are cases, expecially for web servers, in which it is required to link the server certificate with a symbolic link whose name is the hash of the certificate. The following command will do that.


root@myhost:~# cd /etc/ssl/mycerts/
root@myhost:/etc/ssl/mycerts# ln -s wwwCert.pem $(openssl x509 -hash -in wwwCert.pem -noout)
root@myhost:/etc/ssl/mycerts# ls -la
total 16
drwx--x--x 2 root root    4 Nov 17 17:26 .
drwxr-xr-x 9 root root   16 Nov 17 17:14 ..
lrwxrwxrwx 1 root root   11 Nov 17 17:26 a0932462 -> wwwCert.pem
-rw-r--r-- 1 root root 2240 Nov 17 15:35 wwwCert.pem

Creating a user certificate

User certificates are created following the same procedure as the one seen for server certificates. Additional things to be considered refer to the need to encrypt the private key, for secure portability, and the conversion of the certificate to some formats better portable in Microsoft Windows.

Suppose that we have to create a certificate for the user Henry Smith whose email addresses are henry.smith@mycompany.com and henry@mycompany.com. As did for the server certificate, the first step is to update the parameters in the block [ usr_cert ]. Run the command nano /etc/ssl/openssl.cnf, comment out the server section and modify the user section as highlighted in red in the following.


[ usr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

##### for SERVER certificate ######
#nsCertType = server
#keyUsage = digitalSignature, keyEncipherment
#extendedKeyUsage = serverAuth, clientAuth
#subjectAltName = DNS:www.mycompany.com, DNS:mail.mycompany.com

##### for USER certificate ######
nsCertType = client, email
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth, emailProtection
subjectAltName = email:henry.smith@mycompany.com, email:henry@mycompany.com

Now we can generate the certificate signing request.


root@myhost:~# cd /etc/ssl/reqs/
root@myhost:/etc/ssl/reqs# openssl req -newkey rsa:2048 -noenc -keyout userKey.pem -out userReq.pem
..+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+....+......+.....+.+....
..+...+.....+......+...+...+....+.....+..................+...+.......+..+...+.+..+....+++++++++++++++++
...
lot of + and .
...
.......+.........+..+.+.........+........+.+..+..........+...+..+.........+.+..+...............+.+..+..
.....+.....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
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) [US]:
State or Province Name (full name) [California]:
Locality Name (eg, city) [San Francisco]:
Organization Name (eg, company) [My Company]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Henry Smith
Email Address [netadmin@mycompany.com]:henry@mycompany.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

For a user, an RSA private key of 2048 bit is sufficient, but larger sizes can also be used. The only fields to input, in addition to the default ones, are the common name, that is set to the natural name of the person, and the email address. Additional email addresses will be added as subjectAltName during the signing process.

At this point, the certificate request can be signed by the CA. For a user certificate, a reduced validity period is preferable, compared to the one of a server certificate.


root@myhost:/etc/ssl/reqs# openssl ca -in userReq.pem -days 1095 -out userCert.pem -notext
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/cakey.pem: TYPE_YOUR_SECRET
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Nov 17 16:14:18 2022 GMT
            Not After : Nov 16 16:14:18 2025 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = California
            organizationName          = My Company
            commonName                = Henry Smith
            emailAddress              = henry@mycompany.com
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Subject Key Identifier: 
                F7:00:C9:FE:E6:0B:3D:92:96:81:4B:DB:B9:A1:FD:0C:35:A6:8B:C0
            X509v3 Authority Key Identifier: 
                00:32:A8:49:BC:A0:EF:26:DA:50:D0:A4:E6:1C:B0:17:58:57:F6:1F
            Netscape Cert Type: 
                SSL Client, S/MIME
            X509v3 Key Usage: 
                Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, E-mail Protection
            X509v3 Subject Alternative Name: 
                email:henry.smith@mycompany.com, email:henry@mycompany.com
Certificate is to be certified until Nov 16 16:14:18 2025 GMT (1095 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

Now the files can be renamed and moved into the appropriate directories.


root@myhost:/etc/ssl/reqs# mv userKey.pem ../private/HenryKey.pem
root@myhost:/etc/ssl/reqs# mv userCert.pem ../mycerts/HenryCert.pem
root@myhost:/etc/ssl/reqs# mv userReq.pem HenryReq.pem
root@myhost:/etc/ssl/reqs# chmod 600 HenryReq.pem

It is useful to generate an encrypted version of the user's private key, this for allowing safe sharing. The following command carries out this task. Notice that a triple DES cypher is used to assure portability, mainly towards Microsoft Windows systems.


root@myhost:~# cd /etc/ssl/private/
root@myhost:/etc/ssl/private# openssl rsa -des3 -in HenryKey.pem -out HenryKey.encrypted.pem
writing RSA key
Enter pass phrase: A_PASSWORD
Verifying - Enter pass phrase: A_PASSWORD

The secret A_PASSWORD must be confidentially sent to the user Henry Smith, togeter with the private and public keys.

An easier way to send a certificate to a user is to adopt the PKCS12 format, that is also commonly accepted by Microsoft Windows. The following command can be used to produce the PKCS12 certificate.


root@myhost:/etc/ssl/private# openssl pkcs12 -export -inkey HenryKey.pem -in ../mycerts/HenryCert.pem -name "Henry Smith" -certfile ../cacerts/cacert.pem -out HenryCert.p12
Enter Export Password: A_PASSWORD
Verifying - Enter Export Password: A_PASSWORD
root@myhost:/etc/ssl/private# ls -la | grep Henry
-rw------- 1 root root     4794 Nov 17 21:21 HenryCert.p12
-rw------- 1 root root     1854 Nov 17 20:02 HenryKey.encrypted.pem
-rw------- 1 root root     1704 Nov 17 16:53 HenryKey.pem

Generating certificates based on elliptic curve P-256

The Elliptic Curve cryptography is an asymmetric cryptographic scheme alternative to the RSA. Specifically, the elliptic curve P-256 guarantees a security similar to an RSA key of about 3092 bit, even if it is only 256 bit large. OpenSSL can generate private keys based on EC P-256.

Suppose that we need to generate a certificate for, let's say, a router providing IPsec connectivity, whose DNS name is gw.mycompany.com. First, we have to modifiy the openssl.cnf file to include the ipsecIKE key usage.


[ usr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

##### for SERVER certificate ######
nsCertType = server
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth, ipsecIKE
subjectAltName = DNS:gw.mycompany.com

##### for USER certificate ######
#nsCertType = client, email
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
#extendedKeyUsage = clientAuth, emailProtection
#subjectAltName = email:mary.white@mycompany.com, email:mary@mycompany.com

For generating a P-256 private key, we have first to generate the algorithm parameters, then passing them to openssl req.


root@myhost:~# cd /etc/ssl/reqs
root@myhost:/etc/ssl/reqs# openssl ecparam -name prime256v1 -out prime256v1-ecparams.pem
root@myhost:/etc/ssl/reqs# cat prime256v1-ecparams.pem 
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----

Once the algorithm parameters are generated, we can pass them to openssl req for private key and certificate request generation. The key type will be recognized automatically based on the parameters.


root@myhost:/etc/ssl/reqs# openssl req -newkey param:prime256v1-ecparams.pem -noenc -keyout gwKey.pem -out gwReq.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) [US]:
State or Province Name (full name) [California]:
Locality Name (eg, city) [San Francisco]:
Organization Name (eg, company) [My Company]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:gw.mycompany.com
Email Address [netadmin@mycompany.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Finally, the signing process works the same way as did for the other certificate requests.


root@myhost:/etc/ssl/reqs# openssl ca -in gwReq.pem -days 3650 -out gwCert.pem -notext
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/cakey.pem: TYPE_YOUR_SECRET
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 3 (0x3)
        Validity
            Not Before: Nov 18 19:01:04 2022 GMT
            Not After : Nov 15 19:01:04 2032 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = California
            organizationName          = My Company
            commonName                = gw.mycompany.com
            emailAddress              = netadmin@mycompany.com
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Subject Key Identifier: 
                EE:F7:72:C3:9B:4F:A6:A0:AC:56:C0:8C:50:D0:88:7F:AE:2B:27:21
            X509v3 Authority Key Identifier: 
                00:32:A8:49:BC:A0:EF:26:DA:50:D0:A4:E6:1C:B0:17:58:57:F6:1F
            Netscape Cert Type: 
                SSL Server
            X509v3 Key Usage: 
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication, ipsec Internet Key Exchange
            X509v3 Subject Alternative Name: 
                DNS:gw.mycompany.com
Certificate is to be certified until Nov 15 19:01:04 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

We can then finalize by removing the parameters file (we need a new one for each certificate) and by moving the files in the appropriate directories.


root@myhost:/etc/ssl/reqs# rm prime256v1-ecparams.pem
root@myhost:/etc/ssl/reqs# mv gwCert.pem ../mycerts/
root@myhost:/etc/ssl/reqs# mv gwKey.pem ../private/

DISCLAIMER

The material and methods reported in Linux Admin Smart Guide, even if tested, are provided without any guarantee. All the commands are run as privileged (root) user, so it is highly recommended to try them first on non-production machines and, in any case, to always do backups first. Linux Admin Smart Guide is not responsible for any damage or data loss caused by misformulated commands or inadvertently launched commands.

To gain a root shell, run the command sudo su -l from the shell of a regular user who is included in the sudoers list, or simply the command su -l and then providing the root password.


< Prev Next >