In this short article, we’ll show you how to generate your own certification authority and how to sign a self-signed certificate with this certification authority and with completed subjectAltName (Subject Alternative Name) to make it works in Chrome 58 or higher. The main reason for this is mostly for the development, when we want to establish a https connection locally and want it to be trusted. But we can generate this certificates also for intranet domains and, in the worst case, for public domains too.
Why should you ever do with your own certification authority and not just create your own self-signed certificates? The main advantage is that you only need to import this certificate authority to your system/browser (Firefox has its own certificate store), and then all signed certificates by this authority will be automatically trusted. I have to note here, that I’m not a security or linux expert, and I only have merge together guides I found in the one functional unit. It’s possible that something could be done more elegantly, or I will not use the correct terminology. Don’t be afraid to fix me in comments 🙂 This tutorial works at least on Debian Jessie and Stretch, but it’s quite probably, that it will run on multiple systems.
First, we generate a certification authority. We have two options, if we want or don’t want to have a private key protected by a password. This is a simplified tutorial from https://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/. If we don’t want to have a password protected private key, we will use this command:
sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048
And if we want a password protected private key, add the -des3
switch as follows:
sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048
The following procedure is the same for both options:
sudo chmod 600 /etc/ssl/private/rootCA-Development.key sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem
Of course, you can adjust the parameters in -subj
. Their meaning is C=country, ST=state, L=locality and O=organization. After that we need to import file /etc/ssl/certs/rootCA-Development.pem
as trusted to the system or browser (here everyone has to google how to do it for their system/browser).
We just have to create a script that will generate the domain certificates. One or more domains can be entered in one certificate. A wildcard certificate is always generated, so it will also be valid for all subdomains. For this reason, we pass domains to the script without www. So we will create a script with the generate-certificate
name:
sudo nano /usr/local/bin/generate-certificate
With content:
#!/bin/bash ### # How to generate certificate authority: # -> without password: # sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048 # -> with password: # sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048 # # sudo chmod 600 /etc/ssl/private/rootCA-Development.key 2048 # sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem ### if [ "$EUID" -ne 0 ]; then echo "Please run as root" exit 1 fi if [ $# -eq 0 ]; then echo "Please specify domain(s)." echo "Usage: $0 <main domain> [another domain] [another domain] ..." exit 2 fi ROOTCA="Development" # -> for certificate authority with password uncomment the line below: #read -p "Enter rootCA-${ROOTCA}.key password: " PASSWORD DOMAIN=$1 CONF="/tmp/$DOMAIN.openssl.cnf" PRIVATE_KEY="/etc/ssl/private/$DOMAIN.key" CERTIFICATE_REQUEST="/etc/ssl/certs/$DOMAIN.crt.req" CERTIFICATE="/etc/ssl/certs/$DOMAIN.crt" ANOTHER_DOMAINS="" ANOTHER_DOMAINS_INFO="" ANOTHER_DOMAIN_INDEX=3 for ANOTHER_DOMAIN in ${@:2} do ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = ${ANOTHER_DOMAIN}"$'\n' ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1)) ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = *.${ANOTHER_DOMAIN}"$'\n' ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1)) ANOTHER_DOMAINS_INFO="-> ${ANOTHER_DOMAIN}"$'\n' done cat > $CONF <<-EOF [req] default_bits = 2048 prompt = no x509_extensions = v3_req distinguished_name = dn [dn] C = CZ ST = Prague L = Prague O = $ROOTCA CN = *.$DOMAIN [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = $DOMAIN DNS.2 = *.$DOMAIN $ANOTHER_DOMAINS EOF openssl genrsa -out $PRIVATE_KEY 2048 chmod 600 $PRIVATE_KEY openssl req -new -config $CONF -key $PRIVATE_KEY -out $CERTIFICATE_REQUEST openssl x509 -req -in $CERTIFICATE_REQUEST -CA /etc/ssl/certs/rootCA-${ROOTCA}.pem -CAkey /etc/ssl/private/rootCA-${ROOTCA}.key \ -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' # -> for certificate authority with password uncomment the line below and remove this line and the one up # -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' -passin pass:$PASSWORD rm $CERTIFICATE_REQUEST rm $CONF chmod 600 $PRIVATE_KEY echo "Self signed certificate ${CERTIFICATE} and private key ${PRIVATE_KEY} for main domain ${DOMAIN} were generated with 10 years expiration time" if [ -z "$ANOTHER_DOMAINS_INFO" ]; then echo "Another domains:" echo ${ANOTHER_DOMAINS_INFO} fi
A we will set the script as executable:
sudo chmod a+x /usr/local/bin/generate-certificate
If we have generated a private key with a password-protected certificate authority, we must uncomment the line starting with #read -p ...
, and for the openssl x509 ...
command, we must uncomment the third line and delete the second one. The script then always asks for a password before generating the certificate. We can also adjust the certificate information in the [dn]
section as we did with the certification authority.
At the end, we will show a simple example. We generate the certificate for domains domain1.com
and domain2.org
like this:
sudo generate-certificate domain1.com domain2.org
The generated certificate is then in files /etc/ssl/private/domain1.com.key
(private key) and /etc/ssl/private/domain1.com.crt
(certificate). We only need to use these files in nginx, Apache, or other software configuration. This certificate will apply to domains domain1.com code>,
*.domain1.com
, domain2.org
and *.domain2.org
.