SSL is a protocol used to encrypt and authenticate data on networks, typically between a server and a client. The SSL protocol, and its successor, TLS, use asymmetric encryption which is based on two keys: a private and a public one. An SSL certificate provides an encrypted connection and creates an environment of trust, since it certifies the website we are connecting to is effectively what we intend, and no malicious party is trying to impersonate it. Valid SSL certificates are released by a CA (Certificate Authority), but they can also be self-generated. Self signed SSL certificates, while still providing encryption, don’t provide any trust, since the owner and the issuer are the same entity/person. Nonetheless, they can be useful in certain situations: for testing or internal usage, for example.In this tutorial we see how to generate a self-signed SSL certificate and key pair using the OpenSSL toolkit on Linux, how to read the content of a certificate, and how to extract the public key from it.
In this tutorial you will learn:
- How to generate a self-signed SSL certificate and key pair on Linux
- How to read the content of an SSL certificate
- How to extract the public key from a certificate

Software requirements and conventions used
Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution-independent |
Software | OpenSSL toolkit |
Other | None |
Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
Installing the OpenSSL toolkit
The OpenSSL toolkit is available in the official repositories of the most used Linux distributions. It contains a set of utilities and libraries which provide support for various types of protocols and algorithms. There are very high changes the toolkit is already installed on your system, as a dependency of its core packages; however, to install it explicitly, we can just use the package manager of our distribution of choice. On Fedora and other distribution which are part of the Red Hat family, we use dnf
:
$ sudo dnf install openssl
On Debian, Ubuntu and their derivatives, instead, we can use the apt wrapper:
$ sudo apt install openssl
If Archlinux is our daily driver, we can install the OpenSSL toolkit using the pacman package manager. The package is maintained in the “core” repository:
$ sudo pacman -Sy openssl
Once the toolkit is installed we can see how to use it to generate a self-signed certificate.
Generating a self-signed certificate
In order to generate a self-signed certificate, we can make use of one of the many utilities included in the OpenSSL toolkit: req
. This tool is well described in the following way:
The req command primarily creates and processes certificate requests in PKCS#10 format. It can
additionally create self signed certificates for use as root CAs for example.
To generate our certificate, together with a private key, we need to run
req
with the -newkey
option. Let’s see an example of the command. We will discuss it later:
$ openssl req -newkey rsa:4096 -x509 -sha512 -days 365 -nodes -out certificate.pem -keyout privatekey.pem
Let’s analyze the various options we used in the example above. First of all we invoked “req” with the -newkey
option: it is used to create a new certificate request and a private key. It takes one argument which we can use to specify the type of key we want to generate, together with its size. In the example we used: rsa:4096
, so to create an RSA key of 4096 bits. If we omit the key size, the default one is used (2048).
The second option we used is -x509
. What this option does is simply modifying the behavior of the program so that a self-signed certificate is created instead of a certificate request. What is the difference between the two? A certificate request is created on the server where the certificate needs to be installed and sent to a Certificate Authority, which issues the certificate. A self-signed certificate instead, as we already mentioned, is owned and provided by the same person or entity. No Certificate Authority is involved in the process: this is why this type of certificate provides no trust.
With -sha512
we specified the message digest to sign the request/certificate. The default digest is, again, specified in the OpenSSL configuration file, under the default_md
key, and is sha256
. To get the list of all available digest, we can run:
$ openssl list --digest-commands
We should obtain a result similar to the following:
blake2b512 blake2s256 gost md2 md4 md5 rmd160 sha1 sha224 sha256 sha3-224 sha3-256 sha3-384 sha3-512 sha384 sha512 sha512-224 sha512-256 shake128 shake256 sm3
Since we are generating a self-signed certificate, we can decide by ourselves for how long it will be valid. The validity period is expressed in days (30 is the default); the number of days are passed as argument to the -days
option. In this case, we made our certificate value for a whole year.
With the -nodes
option we specified that we don’t want to encrypt the generated private key. Encrypting the private key is without doubts useful: this can be intended as a security measure in case someone stoles it, since to use it, a passphrase should be provided. Just as an example, if we use a private key with Apache, we must provide the passphrase to decrypt it each time we restart the daemon. In this case, since we are generating a self sign certificate, which we will use for testing, therefore we can avoid encrypting the private key.
Finally, we used the -out
and -keyout
options to specify the filenames to write the certificate and the key to, respectively. In this case the certificate will be saved into the certificate.pem
file, and the private key into the privatekey.pem
file. Why did we use “.pem” as the file names suffix? This is because both the certificate and key will be created in PEM format. PEM stands for “Privacy Enhanced Mail”: it is basically a container which includes base64 formatted data.
Providing the certificate information
Once we run the command to generate the certificate, we will be prompted to provide a series of information. Among the others:
- Two letters representing the Country Name (e.g US)
- The full State or Province Name (e.g. California)
- The City name (e.g Los Angeles)
- The Organization or company name (The legal name of the company)
- The fully qualified name of the server
Generating a RSA private key .............................................++++ ...........................++++ writing new private key to 'privatekey.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) [XX]:US State or Province Name (full name) []:California Locality Name (eg, city) [Default City]:Los Angeles Organization Name (eg, company) [Default Company Ltd]:. Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:www.fqdn.com Email Address []:
Reading the content of the certificate
At the end of the process we should find the two created files (certificate.pem and privatekey.pem) in our current working directory. If we take a look at our certificate file we should find a content similar to the following:
-----BEGIN CERTIFICATE----- MIIFfzCCA2egAwIBAgIUYqXQl7Y5G6BAXpQ32GWfekpTEJcwDQYJKoZIhvcNAQEN BQAwTzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAcM C0xvcyBBbmdlbGVzMRUwEwYDVQQDDAx3d3cuZnFkbi5jb20wHhcNMjIwMzIwMjI0 NTU4WhcNMjMwMzIwMjI0NTU4WjBPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs aWZvcm5pYTEUMBIGA1UEBwwLTG9zIEFuZ2VsZXMxFTATBgNVBAMMDHd3dy5mcWRu LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALHf3gnGCATAUEKc xgq3mmwM+wI9HV3SaYEnHgNJnt47FgFHcLWmzMRARrx1ofrwWSYUCGNDidit6FHv fHDyVoH344G8tuyU5YhzddmmphoGpU7jdwbQvtSqcJxOU84KSmwoMp/sIb+iNfSA rcNj1mTMHJJmePwCloDT2/7tuMvBlhfG5JHk5mSwi2GpSi06VqkzKeRBzaJTKEVq vUJNOcBJBCJPhj+I32J3SeJ6YnCfvLyaBzVBR0T+2umGXDTU0KwSnoCg3Swslfma GKDNLzvUerqwxEEUjaKjzdtzclvVJ86xVGI1TiVPdngullHCBdys5PxXabxhv1mF FRgxCXjyctVeEcTx+SIDoxMWVTZFXFbaGUbeXFYEXbm0dzYOj0Y+rbIxvBVGfLDG qngUuIOE3iiaOA/h/V0MuIhFVXg0tO4ZIsN5sZAMpGuLduB5W2soNpb7uRVneEyP VIYwzYT8i4YJMVXCMwQKHQFQbeU2QKTsx0aXnR7O84CUQxCah86FJpzNP5jMjTht 82X08rKGBp5G85hyUQEyvZrtQ9etFHDVdDvfuuFFQf0vXwDUpS7WHOOcK1+M0ztr lxk/vg4qazw7vwXSRD93a1VgnsGAXV8oxKuzUzUCj96JJvjdnd56h3B9ERShEpZx Ua1lgB8sTDG8l3kTpggsfXWHgLTRAgMBAAGjUzBRMB0GA1UdDgQWBBSnylKfTIQJ PNbq+z50Ao0HfrpfMjAfBgNVHSMEGDAWgBSnylKfTIQJPNbq+z50Ao0HfrpfMjAP BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4ICAQBDISi+LunywZWapJFc XbPll/BKbsJNX+4gmMOysFr0QRtDfrXGKN57DlZvfYlkNeBdXi6urGfWuuERbmqo IN2KmYbCTCG5RhfiVvS9MvbQOtItq+tJCIVD2YznblAniU2qy3tquGVLGRSR2SuB X/r8a6NGZ8SzxpeUgQEKYStiIVjkAUrLzn0UXy7ul7pTghy5w4AgiC0AwecnUWwl Dyb+TXadAD0PfHvHMJvMTlfFtVGJgDFPPPAocQ1BHmzxsY01QcXnOfUXGwoldrp5 H5Yf+kbxru6TMPoC8Q0oZqPXX5k4SmOP3npaFQ3q6Zti6Z0EXY1Tq9h0pBTJMXzK B4RX7owrX3k7H2DPZjColyFzjmmdTT75y9CGrDwoKk6RQFDO5/aSfkE3y+KFbQq/ rib/BymCzoYl/4E5LA7SStBk0pTv0qRJEqOhzNdOqkq+xWAEC4JN8a63MY1Fxaii cDgEeYLtdSpfEyB2AsmYDa+hF9lmYP3pcInCsU3iSuYpn8g09iHtCWAvyvcO2tyP JT+Gi6h38jAIAziUI3kXVTbc9tvVfDRlF4mK66z1Iz7loMP4TMSObW35mf200Zvt HqbrhlF8KWMY/IxCM0LNkxQXEIoW3yHm3G3OHoV184XTyW0CKFK18dC8SuYc24cX kLAgdGVMwED+WtoF6hPKfznmIA== -----END CERTIFICATE-----
As we already said, the certificate is PEM-formatted, therefore to read its content, we can issue the following command:
$ openssl x509 -noout -in certificate.pem -text
The x509
utility is used to display and sign certificates. In this case we invoked it with the -noout
option to avoid the encoded version of the certificate to be included in the output, -in
to specify the file containing the certificate to be used as input (certificate.pem, in this case) and -text
to print the output of the certificate in text form. In this case we just wanted to visualize the certificate content on the standard output; to save it to a file we could have used the -out
option and provided the destination filename as its argument, or simply use shell redirection. Here is the output of the command:
Certificate: Data: Version: 3 (0x2) Serial Number: 0f:d2:5a:6c:99:74:37:2e:4b:3a:86:a3:d3:61:95:6a:03:85:04:71 Signature Algorithm: sha512WithRSAEncryption Issuer: C = US, ST = California, L = Los Angeles, CN = www.fqdn.com Validity Not Before: Mar 21 11:03:48 2022 GMT Not After : Mar 21 11:03:48 2023 GMT Subject: C = US, ST = California, L = Los Angeles, CN = www.fqdn.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:b9:6a:fa:50:18:bb:3d:26:80:ef:a4:08:1d:8c: 11:14:c5:5e:81:73:d3:4d:32:b2:86:9a:c2:04:53: 44:74:b8:34:ca:99:42:71:01:30:ae:f3:ef:59:83: fb:bc:8d:e6:ca:b4:7b:6c:82:fe:f5:19:0a:76:26: d6:de:9e:33:62:52:74:a9:63:f9:09:f8:41:4f:9c: 68:0b:23:4c:62:61:ad:59:8e:f5:bc:e8:42:b3:1a: 3d:4e:19:6b:4d:20:b3:42:a5:ae:a1:6f:14:7e:c8: d5:e9:1d:ac:6a:26:5d:ef:40:58:55:b7:21:a6:0d: fb:94:76:a9:95:67:59:c4:2e:5a:42:0f:25:fa:b3: c9:67:38:f2:2f:3b:84:62:d0:6c:1f:b1:ea:58:8b: 12:35:13:45:47:01:d9:66:04:b0:ed:39:cd:e7:ed: 17:a1:ea:bd:27:89:e7:b9:26:96:82:d1:d3:d8:75: 82:f6:f6:07:31:6b:d7:7a:59:87:24:61:0a:3b:29: 97:49:43:ef:26:a1:9e:98:f2:ff:ea:49:01:a0:bf: 9b:45:69:b1:b6:c2:2e:de:e5:e0:43:09:a3:82:46: cf:64:84:d2:eb:dd:7d:08:92:f3:89:e3:51:97:25: 23:be:62:c6:f8:ff:b4:b5:ae:78:a9:ff:81:a8:76: 7b:79:c3:05:55:f0:ce:11:b4:38:00:ef:1f:bd:58: bd:cf:2e:74:ce:30:38:94:d4:64:ab:fc:a9:98:24: 18:dc:e1:10:f8:67:b5:ef:b8:ec:81:60:5d:7a:f3: 1e:01:fe:87:2b:55:71:01:0c:7f:fc:4b:9a:3a:33: 3e:c8:28:33:e6:ad:18:ef:1d:98:33:1e:89:fb:4c: 0b:e8:d2:5a:9d:53:70:2a:12:29:ed:45:79:89:55: 30:4a:f6:5f:41:98:8d:d6:37:d5:a0:02:8a:75:3e: 07:c4:67:45:56:85:c9:8e:5f:25:fb:77:0c:48:94: 29:07:95:f0:07:39:fc:cd:09:02:9b:07:3d:11:8b: 62:4e:e8:5e:fc:c6:a0:41:aa:20:a1:c9:44:63:eb: fd:db:4b:7c:62:1b:b1:46:93:08:37:30:d9:11:84: 0e:ad:97:0b:20:29:41:ba:89:b6:36:84:7d:b6:59: 47:06:86:5a:d6:04:48:b6:87:c8:9c:c7:c3:02:02: 6e:51:ea:11:46:db:d5:b1:9e:e9:75:46:26:5f:9f: 15:92:bc:9c:4b:e2:4d:1b:bc:d5:1b:2e:b0:56:71: fb:4a:20:91:11:8b:31:ae:55:83:e7:e5:96:61:9f: 4d:46:08:02:d3:20:b6:b2:f2:ad:72:78:73:27:a8: 36:92:6f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 62:B1:F4:A8:E1:76:4E:DA:23:67:2D:4B:48:BC:DE:63:4D:7A:15:CB X509v3 Authority Key Identifier: keyid:62:B1:F4:A8:E1:76:4E:DA:23:67:2D:4B:48:BC:DE:63:4D:7A:15:CB X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: sha512WithRSAEncryption 1d:67:0f:7e:5e:0f:13:7b:ce:80:cd:18:d7:01:ce:65:b7:b0: c7:6f:21:1c:41:1c:8b:d8:d1:53:1d:2b:4c:57:2a:60:30:62: d9:d1:1f:6d:ff:8e:56:d0:8b:0b:b1:83:ee:a9:b4:d6:84:cd: ca:c6:9c:f8:84:7c:47:7b:c6:08:6d:b2:20:9b:88:02:4b:5c: 30:32:17:2d:37:a6:a3:de:24:14:fb:8c:d1:82:1d:bc:4e:2e: 52:a4:87:8d:98:fc:4b:b1:e2:ac:2a:ed:f9:e9:21:36:bc:a0: 90:f5:a3:f7:f5:5a:e7:5e:aa:a7:58:b6:97:b5:b0:73:f5:03: 14:91:b1:fe:41:49:05:17:e4:fb:0d:be:07:38:86:9d:b4:5a: 02:c7:91:e9:c0:c1:53:59:e5:3f:60:2c:cb:fe:15:94:30:67: f2:a9:1a:d9:a1:71:49:43:a9:45:cb:97:14:7f:e7:6a:9d:19: 41:95:db:01:d9:ba:fc:5f:51:43:5b:cd:14:ff:4b:b0:63:7c: 6b:76:54:86:b9:c6:a2:92:16:7c:22:09:eb:b6:4c:4a:85:40: e8:9f:fb:0a:40:ff:2d:c6:75:06:f9:67:ba:2e:63:4e:25:0e: bb:0d:e0:d4:05:9c:ce:c5:b4:36:19:58:db:87:f6:af:1c:4d: 45:2b:de:ec:f2:9a:4a:e2:0e:63:5f:bb:fa:15:20:35:10:93: ce:23:35:33:16:f8:61:c0:6e:48:12:55:29:d2:5a:41:d1:9a: 47:ef:d9:fd:54:91:15:a0:4b:83:b2:f6:78:1d:98:e5:71:03: 2a:4b:eb:db:49:78:61:85:16:71:ea:a6:ed:8e:64:98:00:e0: 73:9a:66:4b:4c:30:b7:d3:a7:0c:bb:af:09:cc:5c:c1:7a:ef: 9c:42:19:1b:95:e4:25:37:ba:cf:db:74:1f:cd:a3:a9:84:11: 39:27:62:59:60:7e:b4:82:e6:a0:33:bd:e9:32:6a:86:61:86: cf:dc:1e:f0:93:b7:42:7d:92:5d:39:df:c2:60:1b:5a:b4:0d: 5e:20:92:7a:d4:09:4f:2e:87:81:34:bb:aa:75:97:b1:f8:23: bd:ff:63:12:fa:d2:3b:8b:8c:74:7c:1b:16:2b:0a:5b:94:69: 22:58:45:d2:0f:75:16:26:60:d9:81:7b:e9:83:79:26:b0:c0: 32:ca:46:80:07:eb:df:8e:00:c8:fa:17:a5:e1:e2:24:cc:2c: a6:13:a2:0d:35:d6:5a:1a:d1:5e:a2:d7:83:69:32:73:af:77: ed:6a:13:7b:60:d2:2c:78:f2:0d:4b:04:ec:c6:57:38:50:ee: a4:ab:c0:b0:24:4b:01:70
Extracting the public key from a certificate
As we saw, SSL/TLS is based on asymmetric encryption, and the use of a private and a public key. The private key must remain secure on the server, while the public key is sent to the client together with the certificate. How can we extract the public key included in it? Well, it is a very simple operation. To accomplish this task we must use again the -x509
command. To extract the public key from the certificate we generated in this tutorial, we would run:
$ openssl x509 -pubkey -noout -in certificate.pem
We invoked x509, this time using the
-pubkey
option, which makes so that the certificate public key is printed in PEM format:
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuWr6UBi7PSaA76QIHYwR FMVegXPTTTKyhprCBFNEdLg0yplCcQEwrvPvWYP7vI3myrR7bIL+9RkKdibW3p4z YlJ0qWP5CfhBT5xoCyNMYmGtWY71vOhCsxo9ThlrTSCzQqWuoW8UfsjV6R2saiZd 70BYVbchpg37lHaplWdZxC5aQg8l+rPJZzjyLzuEYtBsH7HqWIsSNRNFRwHZZgSw 7TnN5+0Xoeq9J4nnuSaWgtHT2HWC9vYHMWvXelmHJGEKOymXSUPvJqGemPL/6kkB oL+bRWmxtsIu3uXgQwmjgkbPZITS6919CJLzieNRlyUjvmLG+P+0ta54qf+BqHZ7 ecMFVfDOEbQ4AO8fvVi9zy50zjA4lNRkq/ypmCQY3OEQ+Ge177jsgWBdevMeAf6H K1VxAQx//EuaOjM+yCgz5q0Y7x2YMx6J+0wL6NJanVNwKhIp7UV5iVUwSvZfQZiN 1jfVoAKKdT4HxGdFVoXJjl8l+3cMSJQpB5XwBzn8zQkCmwc9EYtiTuhe/MagQaog oclEY+v920t8YhuxRpMINzDZEYQOrZcLIClBuom2NoR9tllHBoZa1gRItofInMfD AgJuUeoRRtvVsZ7pdUYmX58VkrycS+JNG7zVGy6wVnH7SiCREYsxrlWD5+WWYZ9N RggC0yC2svKtcnhzJ6g2km8CAwEAAQ== -----END PUBLIC KEY-----
Closing thoughts
In this tutorial we learned how to generate a self-signed SSL certificate using the OpenSSL toolkit and the “req” command. We saw how to provide the certificate information and how to set its validity in days. Finally, we saw how to read the content of the certificate and how to extract the public key in pem format from it.