How To Write Your Own SSL Certificate in 15 minutes
All major sites have long switched to the https protocol. The trend continues, and many of our readers interested to secure their website to work on a secure protocol. And if a backend is developed for a mobile application, then https is required. For example, Apple requires that the server’s data exchange with the application is done via a secure protocol. This requirement was introduced from the end of 2016.
On production, there are no problems with certificates. Usually, the hosting provider provides a convenient interface for connecting the certificate. Issuing a certificate is also not a difficult matter. But while working on the project, each developer should take care of the certificate himself.
- In this article, I’ll show you how to release a self-signed SSL certificate and get the browser to trust it.
To issue a certificate for your local domain, you will need a root certificate. On its basis, all other certificates will be issued. Yes, for each new top-level domain, you need to issue your own certificate.
Notes: Someone might even say that It’s easier to buy any cheap Domain Name and get a certificate from Letsencrypt for free than to deal with this nonsense. But this article was specifically written for those developers how are interested in creating their own product and loves to experiment with a couple lines of code.
First, form the private key:
openssl genrsa -out rootCA.key 2048
Then the certificate itself:
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem
It will be necessary to enter the country, city, company, etc.
As a result, we get two files:
- rootCA.key
- rootCA.pem
We pass to the main thing, the release of a self-signed certificate. As with the root, these are two teams. But the parameters for the teams will be much larger. And we need an auxiliary configuration file. Therefore, we will write all this in the form of bash script create_certificate_for_domain.sh
The first parameter is mandatory, we will derive a small instruction for the user.
if [ -z "$1" ] then echo "Please supply a subdomain to create a certificate for"; echo "e.g. mysite.localhost" exit; fi
Create a new private key if it does not exist or we will use the existing one:
if [ -f device.key ]; then KEY_OPT="-key" else KEY_OPT="-keyout" fi
Here, we are going to ask the user for the domain name. Add the ability to specify a “common name” (it is used to form a certificate):
DOMAIN=$1 COMMON_NAME=${2:-$1}
In order not to answer questions in interactive mode, we will form a string with answers. And we set the validity period for the certificate:
SUBJECT="/C=CA/ST=None/L=NB/O=None/CN=$COMMON_NAME" NUM_OF_DAYS=999
The SUBJECT variable lists all the same questions that were asked when creating a root certificate (country, city, company, etc). All the value except CN can be changed at your discretion.
Now, creating a CSR file (Certificate Signing Request) based on the key. More information about the certificate request file can be found in this article.
openssl req -new -newkey rsa:2048 -sha256 -nodes $KEY_OPT device.key -subj "$SUBJECT" -out device.csr
Form the certificate file. To do this, we need an auxiliary file with the settings. In this file, we will write the domains for which the certificate will be valid and some other settings. Call it v3.ext. Pay your attention that this is a separate file, not part of the bash script.
authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = %%DOMAIN%% DNS.2 = *.%%DOMAIN%%
Yes, you are right, our certificate will be valid for the main domain, as well as for all subdomains. Save the above lines to the file v3.ext
We return to our bash script. On the basis of the auxiliary file v3.ext we create a temporary file with the indication of our domain:
cat v3.ext | sed s/%%DOMAIN%%/$COMMON_NAME/g > /tmp/__v3.ext
Issue the certificate:
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days $NUM_OF_DAYS -sha256 -extfile /tmp/__v3.ext
Rename the certificate and delete the temporary file:
mv device.csr $DOMAIN.csr cp device.crt $DOMAIN.crt # remove temp file rm -f device.crt;
The script is ready. Now, time to run it:
./create_certificate_for_domain.sh mysite.localhost
We get two files:
- mysite.localhost.crt
- devise.key
Now, you need to specify the web server paths to these files. For nginx, this would look like this:
Launch the browser, open https: //mysite.localhost and see:
The browser does not trust this certificate. How to be?
It is necessary to note the certificate issued by us as Trusted. On Linux (Ubuntu and, probably, other Debian-based distributions) this can be done through the browser itself. In Mac OS X, this can be done through the Keychain Access application. Run the application and drag the file mysite.localhost.crt to the window. Then open the added file and select Always Trust:
We update the page in the browser and:
Success! The browser trusts our certificate.
A certificate can be shared with other developers so that they add it to themselves. And if you use Docker, then the certificate can be saved there.