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.
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.
It’s still working however when trying to connect to my FTP SSL enabled Server with FileZilla I get the following Error Message :
Running this command I get
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 :
So is there a simple way out of this situation ? I have just upgraded to Ubuntu 22.04 which sports this openssl v3.
You can create a custom file with below content
and pass this using
-extfile
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.
By this command we generated two files,
server.key
in theprivate
folder andserver.crt
in thecerts
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.
We must modify the openssl’s “
default-ssl.conf
” file.Default location in apache2:
We need to change the default file, such as
ssl-cert-snakeoil.pem
andssl-cert-snakeoil.key
byserver.crt
andserver.key
.Apply this command:
Part Second
Configure the virtual host configuration file.
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.
This command will show you the options. Reconfigure and reload the
apache2
, if needed start theapache2
again.Test case: if you want to remove openssl
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.
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
+1
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.
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
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.
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)