Stop using old SHA-1 SSL certificates

Last updated by Henry

Retiring Broken SHA1

The word is out on SHA-1 secure hashing algorithm which has been broken by Google using AlphaGo, artificial intelligence (AI) that runs on Google Cloud, Google Photo.


Starting with version 56, Chrome browsers mark SHA1-signed certificates as unsafe. Other browsers are giving similar warnings. When we started seeing the above warning on our virtual intranet (a fake internal network of virtual machines with made-up host and domain names), we thought something was wrong. No, it was just the old software that created our certificates was signing them with SHA1.

Wildcard SSL Certificate Authority

It was time to upgrade the certificates on our intranet. While we were at it, we decided to create our own certificate authority and use it to build our own little top-level domain (TLD). In retrospect, having a TLD, even a fake intranet internal company TLD, is not much of an advantage.

With the usual second-level domain, such as, the whole intranet can get away with using a single wildcard certificate covering and, etc. That is probably why it is easier to go with the standard practice and set up a domain (usually a second-level domain like a normal company would use) and have other computers on the network join that domain. It's the default setup, and it's how everybody does it.

But we're different. We have an ego the size of Alaska and we are going to set up a TLD anyway.

Setting Up a Top-Level Domain

With a top-level domain (.K) we are going to have to create a new certificate for every host on the network. Why? Because for security reasons, browsers hard-coded wildcard certificates not to work across a swath of second-level domains. The standard wildcard certificate not only will not work on our network, it will never work.

So let's outline how we set up a TLD on our Fedora server.

Setting up dnsmasq. Dnsmasq is a DNS server that comes pre-installed. We just have to set up dnsmasq.conf to create the .K TLD pointing to localhost,

Enable the dnsmasq service

systemctl enable dnsmasq.service

Every host is now a second-level domain and needs a separate certificate. No big deal. We can issue each of them a wildcard certificate covering all their subhosts. We can have a miniature internet in a box.

Create a folder to hold the scripts and create v3.ext
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
DNS.1 = %%DOMAIN%%
DNS.2 = *.%%DOMAIN%

Next, we created three scripts to create our certificate authority (CA) and issue certificates for each domain.
echo Generate CA key & certificate
echo Common Name (CN) may be or localhost
openssl genrsa -out rootCA.key 4096 -cy authority
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

Now we have to make a script to use our CA to sign a certificate for each made-up domain on the network.
: ${1?"Create certificate
Usage: $0 "}
# Generate client key & certificate signing request
openssl genrsa -out $1.key 2048

openssl req -new -newkey rsa:2048 -sha256 -nodes -key $1.key -subj "$SUBJECT" -out $1.csr
cat v3.ext | sed s/%%DOMAIN%%/$DOMAIN/g > /tmp/xv3.ext
openssl x509 -req -in $1.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial 

# Generate client certificate
openssl x509 -req -in $1.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out $1.crt -days 1024 -sha256 -extfile /tmp/xv3.ext
rm -f $1-chain.crt
cat $1.crt rootCA.pem > $1-chain.crt
chmod 400 $1-chain.crt

Finally, we need a script to install the certificate into the system so browsers recognize the CA.
# "Install" certificates somewhere for apache conf to find them later
sudo cp *.crt *.pem /etc/pki/tls/certs/
sudo cp *.key /etc/pki/tls/private/
sudo cp /etc/pki/tls/certs/rootCA.pem /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
sudo apachectl restart
# note: If the certificate is in OpenSSL’s extended BEGIN TRUSTED CERTIFICATE format, place it in /etc/pki/ca-trust/source
cat <<DOC
Certificates installed!
Our rootCA.crt certificate should be showing up in the browser's configuration, e.g. Chrome->Manage certificates->AUTHORITIES
Configure Apache's /etc/httpd/conf.d/ssl.conf with the server's Common Name (CN) files:
SSLCertificateFile /etc/pki/tls/certs/CN.crt
SSLCertificateKeyFile /etc/pki/tls/private/CN.key
SSLCertificateChainFile /etc/pki/tls/certs/CN-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rootCA.pem
Then, restart apache
apachectl restart
Navigate to chrome://restart

After creating the scripts and running them, we should now have certificates for each domain. We can serve up multiple secure domains on Apache 2.0 by editing ssl.conf

Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost _default_:443>
DocumentRoot "/var/www/html"
ServerName localhost:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/tls/certs/k.crt
SSLCertificateKeyFile /etc/pki/tls/private/k.key
SSLCertificateChainFile /etc/pki/tls/certs/k-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rootCA.pem
SSLVerifyClient none
<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars
BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

And for each domain


<VirtualHost *:*>
ServerName MyDomain.k
ServerAlias *.MyDomain.k
DocumentRoot "/var/www/html/mydomain"
<VirtualHost *:443>
ServerName MyDomain.k
ServerAlias *.MyDomain.k
DocumentRoot "/var/www/html/mydomain"
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/MyDomain.k.crt
SSLCertificateKeyFile /etc/pki/tls/private/MyDomain.k.key
SSLCertificateChainFile /etc/pki/tls/certs/MyDomain.k-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rootCA.pem

<VirtualHost *:*>
ServerName MyOtherDomain.k
ServerAlias *.MyOtherDomain.k
DocumentRoot "/var/www/html/myotherdomain"
<VirtualHost *:443>
ServerName MyOtherDomain.k
ServerAlias *.MyOtherDomain.k
DocumentRoot "/var/www/html/myotherdomain"
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/MyOtherDomain.k.crt
SSLCertificateKeyFile /etc/pki/tls/private/MyOtherDomain.k.key
SSLCertificateChainFile /etc/pki/tls/certs/MyOtherDomain.k-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rootCA.pem

To be continued as time permits...





Reference Links

Create a self-signed CA & client certificate


Trusting additional CAs in Fedora / RHEL / CentOS

Apache SSL Certificate Installation

add -cy authority to the switches when creating the cert authority

add -extfile v3.ext to the switches

Getting Chrome to accept self-signed localhost certificate

Can a wildcard SSL certificate be issued for a second level domain?