Steps to create Self-Signed Certificate with OpenSSL


OpenSSL, Security

The name self-signed certificate itself explains it's meaning i.e. we are not using an CA (Certificate Authority) to sign the certificate and instead we our self will sign the certificate.

We tend to use self-signed certificate for most of our internal communications where there is less to no risk of any data breach. Adding self-signed certificate will add an encryption layer so this is not the best way for data transmission but it is still better than plain text. So if an intruder manages to access the packets of data communication then he/she will not be able to view the data as it will in encrypted format.

In this tutorial I will cover different use cases and methods to create self-signed certificate using openssl command.

 

1. Create Self-Signed Certificate without Password

In this section we will create a self-signed certificate using RSA algorithm which does not require a password.

Generate the Private Key:

openssl genpkey -algorithm RSA -out mykey.pem

Generate a Certificate Signing Request (CSR):

openssl req -new -key mykey.pem -out mycsr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com"

Generate the Self-Signed Certificate:

openssl x509 -req -days 365 -in mycsr.csr -signkey mykey.pem -out cert.pem

 

2. Create Self-Signed Certificate With a Password

We can also choose to secure our private key with a password. There are a couple of ways using which we can pass the password when creating slf-signed certificates, we will cover all such possible methods:

 

2.1 Using an Environment Variable

We can use environment variable to pass the secure password to the openssl command. This is considered more secure as it avoids exposing the password directly via command line.

Set the Environment Variable:

export MY_SECRET_PASS="YourStrongPassword"

Generate the Encrypted Private Key:

openssl genpkey -algorithm RSA -aes256 -out mykey.pem -passout env:MY_KEY_PASS

Generate the Certificate Signing Request (CSR):

openssl req -new -key mykey.pem -out mycsr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com" -passin env:MY_KEY_PASS

Generate the Certificate:

openssl x509 -req -days 365 -in mycsr.csr -signkey mykey.pem -out cert.pem -passin env:MY_KEY_PASS

Clean Up:

After the process, remove the environment variable to ensure it's not left in memory:

unset MY_KEY_PASS

 

2.2 Prompting for the Password

Setting environment variable can be considered secure but it also has it's own downside so we also have an option to prompt for password instead of storing in a variable which can still be exposed.

Generate the Encrypted Private Key:

openssl genpkey -algorithm RSA -aes256 -out mykey.pem -passout stdin

Generate the CSR:

openssl req -new -key mykey.pem -out mycsr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com" -passin stdin

Generate the Self-Signed Certificate:

openssl x509 -req -days 365 -in mycsr.csr -signkey mykey.pem -out cert.pem -passin stdin

 

2.3 Using Password File

We can also create a file which stores the password and pass the file as an input to openssl command.

Create a Password File:

echo "YourStrongPassword" > passwordfile
chmod 600 passwordfile

Generate the Encrypted Private Key:

openssl genpkey -algorithm RSA -aes256 -out mykey.pem -passout file:./passwordfile

Generate the CSR:

openssl req -new -key mykey.pem -out mycsr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com" -passin file:./passwordfile

Generate the Self-Signed Certificate:

openssl x509 -req -days 365 -in mycsr.csr -signkey mykey.pem -out cert.pem -passin file:./passwordfile

Secure the Password File:

shred -u passwordfile

 

3. Create Self-Signed Certificate using RSA Key

Generate the RSA Private Key:

openssl genpkey -algorithm RSA -out rsa_key.pem

Create a CSR:

openssl req -new -key rsa_key.pem -out rsa_csr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com"

Generate the RSA Certificate:

openssl x509 -req -days 365 -in rsa_csr.csr -signkey rsa_key.pem -out rsa_cert.pem

 

4. Create Self-Signed Certificate using ECDSA Key

Generate the ECDSA Private Key:

openssl ecparam -name prime256v1 -genkey -out ecdsa_key.pem

Create a CSR:

openssl req -new -key ecdsa_key.pem -out ecdsa_csr.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=Department/CN=www.example.com"

Generate the ECDSA Certificate:

openssl x509 -req -days 365 -in ecdsa_csr.csr -signkey ecdsa_key.pem -out ecdsa_cert.pem

 

5. Create Self-Signed Certificate using single OpenSSL command

For simplicity and automation we can also combine all openssl commands which includes generating private key, CSR and signing CSR into one single command to create self-signed certificate:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=US/ST=California/L=City/O=Organization/OU=Department/CN=www.example.com"

 

You can next again use openssl command to view the certificate and private key content.

 

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

10 thoughts on “Steps to create Self-Signed Certificate with OpenSSL”

  1. I used to allow SSL on Ubuntu vsftpd FTP Server for connecting my Canon camera on it. This command line was working fine before version 3 of OpenSSL.

    $ sudo openssl req -x509 -nodes -days 40000 -newkey rsa:4096 -keyout /etc/ssl/private/vsftpd.key -out /etc/ssl/private/vsftpd.pem -extensions eos5d4

    It’s still working however when trying to connect to my FTP SSL enabled Server with FileZilla I get the following Error Message :

    Error:	GnuTLS error -48: Key usage violation in certificate has been detected.

    Running this command I get

    $ echo | openssl s_client -connect google.com:443 2>/dev/null | openssl x509 -noout -text | grep -i -A1 usage
                X509v3 Key Usage: critical
                    Digital Signature
                X509v3 Extended Key Usage: 
                    TLS Web Server Authentication
    $ 

    Meaning probably the flag Server Auth isn’t there (by default I guess).

    I have read in various places that I need a configuration file. I have used one found on this website like :

    [ req ]
    distinguished_name  = req_distinguished_name
    policy              = policy_match
    x509_extensions     = user_crt
    req_extensions      = v3_req
    
    [ 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) ## Print this message
    stateOrProvinceName_default     = 
    localityName                    = Locality Name (eg, city) ## Print this message
    localityName_default            = 
    0.organizationName              = Organization Name (eg, company) ## Print this message
    0.organizationName_default      = 
    organizationalUnitName          = Organizational Unit Name (eg, section) ## Print this message
    organizationalUnitName_default  = Admin ## This is the default value
    commonName                      = Common Name (eg, your name or your server hostname) ## Print this message
    commonName_max                  = 64
    emailAddress                    = Email Address ## Print this message
    emailAddress_max                = 64
    
    [ user_crt ]
    nsCertType              = client, server, email
    nsComment               = "OpenSSL Generated Certificate"
    subjectKeyIdentifier    = hash
    authorityKeyIdentifier  = keyid,issuer
    
    [ v3_req ]
    basicConstraints        = CA:FALSE
    extendedKeyUsage        = serverAuth, clientAuth, codeSigning, critical, emailProtection
    keyUsage                = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign, keyAgreement
    
    However adding a -config openssl.cnf to the above command fails. With :
    
    req: Use -help for summary.

    So is there a simple way out of this situation ? I have just upgraded to Ubuntu 22.04 which sports this openssl v3.

    Reply
    • You can create a custom file with below content

      # cat client_cert_ext.cnf
      basicConstraints = CA:FALSE
      nsCertType = client, email
      nsComment = "OpenSSL Generated Client Certificate"
      subjectKeyIdentifier = hash
      authorityKeyIdentifier = keyid,issuer
      keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
      extendedKeyUsage = clientAuth, emailProtection

      and pass this using -extfile

      openssl x509 -req -in client.csr -CA  -CAkey  -out client.cert.pem -CAcreateserial -days 365 -sha256 -extfile client_cert_ext.cnf
      Reply
  2. Create self-signed certificate – Ubuntu
    This tutorial assumes that you know how to configure an apache2 server, the virtual host configuration file, and an index.html file.
    Part one
    Install the openssl (sudo apt-get install -y openssl). After installing the openssl – there were two directories created certs and private in addition to files.

    $sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/server.key -out /etc/ssl/certs/server.crt
    Please fill in the pop-up form and feel free to experiment:
    Country Name (2 letter code) [AU]:AU
    State or Province Name (full name) [Some-State]:Victoria
    Locality Name (eg, city) []: Melbourne
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Liqustra Pty Ltd
    Organizational Unit Name (eg, section) []:IT Department
    Common Name (e.g. server FQDN or YOUR name) []:server IP address or domain name
    Email Address []:your email address

    By this command we generated two files, server.key in the private folder and server.crt in the certs folder (you can give any name you want in the command).
    Please note: You have to have the execute permission to the private directory/folder.

    To allow permission, just type this command.

    sudo chmod +x private

    We must modify the openssl’s “default-ssl.conf” file.
    Default location in apache2:

    $sudo nano /etc/apache2/sites-available/default-ssl.conf
    Below is the default configuration:
    SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

    We need to change the default file, such as ssl-cert-snakeoil.pem and ssl-cert-snakeoil.key by server.crt and server.key.

    Apply this command:

    $sudo a2enmod ssl
    $sudo systemctl reload apache2

    Part Second
    Configure the virtual host configuration file.

        ServerAdmin admin@liqustra.com
        ServerName liqustra.com
        ServerAlias www.liqustra.com
        DocumentRoot /var/www/liqustra.com
       SSLEngine on
       SSLCertificateFile  /etc/ssl/certs/server.crt
       SSLCertificateKeyFile /etc/ssl/private/server.key
    
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined

    Part Three
    Open Firefox in the Ubuntu machine.
    Type: https://IP Address or domain name
    You will get warning sign, because it is a private certificate. Any way for now do the practice and you will be able to access the website by protocol https, instead of http.


    The self-signed certificate is authenticated by Firefox in my case, because I open the website several times.

    Part Four
    Troubleshooting. You can use the following command if you face any problem.

    $sudo apache2ctl configtest

    This command will show you the options. Reconfigure and reload the apache2, if needed start the apache2 again.
    Test case: if you want to remove openssl

    sudo apt-get remove -y openssl
    Reply
  3. I’m confused about the encrypted password part. The -passin and -passout options are for pass phrases, and do not support binary keys. They stop at the first newline character, which could easily appear in the output binary file when you do openssl enc. So even though this may appear to work, the actual pass phrase used to encrypt your private key may be unexpectedly short.

    I may be wrong, but I think you’d have to pass the decrypted data to -passin and -passout.

    If you run this command to try and verify your server private key, you’ll see it is not, in fact, encrypted with the secret pass phrase (which was “secret”):
    openssl rsa -noout -text -in server.key -passin pass:secret
    Yes, using -passin file:mypass.enc will successfully open the key, but the point is that the pass phrase is some unknown set of characters, ending at the first newline character.

    Reply
    • Hi Ron, This is a good observation, somehow even I didn’t noticed may be because I assumed it will work the other way. Let me check this and get back to you

      Reply
      • I missed to respond. I had checked this and this seems to be expected behaviour.
        You are not giving a plain text password instead you are giving an encrypted password so openssl will treat it as incorrect password. Have confirmed it with the developers.

        Reply
        • I’m not sure how to interpret that last response. Does this mean the whole approach is flawed and therefore the topic is pointless?

          Meanwhile I’m confused about the step “enter aes-256-cbc encryption password:” when first creating the .enc file. Was anything entered here for a password? When I left it blank no encrypted file was output. However if its not blank then won’t the entered value be required every time

          Reply
          • I am not sure if I understand your first question

            Regarding the empty passphrase. If you choose aes256, des3 or similar algorithm for your private key then it becomes mandatory to provide a passphrase which will be used to encrypt the private key. Here empty passphrase is not allowed. And yes if you give passphrase, during any connection which requires private key (mTLS) then before the authentication you will have to provide the password to decrypt the key before using. This depends on end user’s requirement to choose to use a secure or non-secure key.

            Reply
  4. I wonder: In creating the CA, you do
    (umask 077; openssl genrsa 1024 > serverkey.pem)
    but isn’t this part of creating a server request?. If you are to sign request made by others, there is no access to this data. (in case of self-signed, it doesn’t matter, otherwise it is)

    Reply

Leave a Comment