Generating Chrome 58+ Compatible Self-Signed SSL Certificates with Subject Alternative Name (SAN) Using OpenSSL


2 views

Since Chrome 58 (released April 2017), the browser enforces stricter SSL certificate validation by requiring Subject Alternative Name (SAN) fields instead of just Common Name (CN). This change broke many existing self-signed certificate setups, throwing ERR_CERT_COMMON_NAME_INVALID errors.

Here's the definitive method to create SAN-enabled certificates that work in modern Chrome:

# Generate private key (keep this secure!)
openssl genrsa -out server.key 2048

# Create config file (san.cnf)
cat << EOF > san.cnf
[ req ]
default_bits       = 2048
prompt             = no
default_md         = sha256
distinguished_name = dn
req_extensions     = req_ext

[ dn ]
C  = US
ST = California
L  = San Francisco
O  = Your Organization
CN = yourdomain.local

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = yourdomain.local
DNS.2 = *.yourdomain.local
IP.1  = 192.168.1.1
EOF

# Generate CSR
openssl req -new -key server.key -out server.csr -config san.cnf

# Create self-signed cert (valid 10 years)
openssl x509 -req -in server.csr -signkey server.key -out server.crt \
  -days 3650 -extfile san.cnf -extensions req_ext

For local development on macOS:

# Add to system keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crt

# For Firefox (separate cert store)
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n "Local Cert" -i server.crt

Always verify your certificate before deployment:

openssl x509 -in server.crt -text -noout | grep -A 1 "Subject Alternative Name"

# Should show:
# X509v3 Subject Alternative Name: 
#     DNS:yourdomain.local, DNS:*.yourdomain.local, IP Address:192.168.1.1
  • Missing the -extensions flag when signing
  • Using SHA-1 instead of SHA-256
  • Not including both bare domain and wildcard in SAN
  • Forgetting to restart web servers after certificate changes

For production-like environments, consider adding these extensions to your config:

[ req_ext ]
subjectAltName = @alt_names
basicConstraints = critical,CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

Since Chrome 58, the browser enforces stricter SSL certificate validation by requiring Subject Alternative Name (SAN) instead of relying solely on Common Name (CN). This change broke many existing self-signed certificate setups. Here's how to properly generate a certificate that Chrome will accept.

First, create a configuration file (let's name it san.cnf) with these contents:

[ req ]
default_bits        = 2048
default_keyfile     = server.key
distinguished_name  = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = v3_ca
prompt             = no

[ req_distinguished_name ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
commonName          = dev.mycompany.com

[ req_ext ]
subjectAltName      = @alt_names

[ v3_ca ]
subjectAltName      = @alt_names
basicConstraints    = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
extendedKeyUsage    = serverAuth

[ alt_names ]
DNS.1               = dev.mycompany.com
DNS.2               = localhost
IP.1                = 127.0.0.1

Execute these commands to generate both private key and certificate in one step:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout server.key -out server.crt -config san.cnf \
-extensions 'v3_ca'

Check your certificate contains the SAN extension:

openssl x509 -in server.crt -text -noout | grep -A 1 "Subject Alternative Name"

You should see output showing your configured SAN entries.

For Chrome to accept your certificate:

  1. Double-click the server.crt file to open it in Keychain Access
  2. Select "System" in the Keychain dropdown
  3. Find your certificate, double-click it
  4. Expand the "Trust" section
  5. Set "When using this certificate" to "Always Trust"
  6. Close the window and authenticate to save changes

If Chrome still shows ERR_CERT_COMMON_NAME_INVALID:

  • Restart Chrome completely (all instances)
  • Ensure you're accessing the site via exactly the domain listed in SAN
  • Check certificate validity dates with: openssl x509 -in server.crt -text -noout | grep -i validity