Creating and Trusting Self-Signed Certs on MacOS and Chrome

In this post, I'll explain how to create a self-signed certificate configure Chrome on your macOS to trust it for local development.

By Last Updated: June 21, 2024 7 minutes read

A few years ago I write a post Set up Self-Signed Certificates & Trusting them on OS X. I use Chrome as my primary browser which had a few changes both to the way it handles SSL certs. Since I know I’ll have to do this again in the future, I’m updating the post to reflect those changes if for no other reason, so I have something to go back to in the future.

There are two parts to this process:

  • creating the self-signed cert
  • adding the self-signed cert to the machine’s Trusted Root Authority

Workarounds

There are two workarounds you can leverage to avoid these issues… but use them at your own risk. I would skip this section and just do it the right way. They are listed here for information only.

Temporary Workaround

There is a temporary workaround. Until Chrome 65, you can configure Chrome to respect the old commonName behavior with the EnableCommonNameFallbackForLocalAnchors setting.

On Windows, add the following registry key

reg add HKLM\Software\Policies\Google\Chrome /v EnableCommonNameFallbackForLocalAnchors /t REG_DWORD /d 1

On MacOS, run the following:

defaults write com.google.Chrome EnableCommonNameFallbackForLocalAnchors -bool true

Dangerous Workaround

Another option is to simply launch Chrome and instruct it to ignore all certificate warnings. Launch Chrome with the --ignore-certificate-errors argument.

This works when you work with your self-signed certs, but you should never browse the web in this mode.

Creating the Self-Signed Cert

Last time I did this, I used the openssl utility. It wasn’t too hard, but one thing that changed is how Chrome respects certificates.

As of Chrome 58, you can’t just identify the host using the commonName property. You must now also include the host in the subjectAltName property as well. The trick is you can’t specify the subjectAltName property using just the command line openssl tool.

Instead you must use a configuration file. What I did was take the default openssl configuration file on my machine, copy it and make a few edits. Here’s what the final one looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default = US

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = FL

localityName          = Locality Name (eg, city)
localityName_default  = Florida

organizationName         = Organization Name (eg, company)
organizationName_default = Andrew Connell Inc.

# Use a friendly name here because its presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default  = localhost

emailAddress         = Email Address
emailAddress_default = [email protected]

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints  = CA:FALSE
keyUsage          = digitalSignature, keyEncipherment
subjectAltName    = @alternate_names
nsComment         = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints    = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName      = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = localhost
DNS.2       = localhost.localdomain
DNS.3       = 127.0.0.1

# DNS.1       = example.com
# DNS.2       = www.example.com
# DNS.3       = mail.example.com
# DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

The things to note are:

  • lines 69-73: I specify the alternate URLs I want the cert to be registered for… in this case localhost
  • line 61: the alternate URLs are used in the subjectAltName property for the cert.
If you use this configuration file, take note I’ve also updated my defaults in lines 12-33 this gist. You might want to change those for your use.

With the config file set up, now you can create the certificate. Run the following command (do it on one line… I’ve broken it up for readability):

openssl req
  -config openssl.conf
  -new -x509 -sha256
  -newkey rsa:2048
  -nodes
  -days 1000
  -keyout localhost.andrewconnell.key.pem
  -out localhost.andrewconnell.cert.pem

What are all these properties?

  • req: PKCS#10 certificate request and certificate generating utility
  • config: The configuration file to use.
  • new x590 sha256: Create a new key and output a self signed certificate instead of a certificate request; this is typically used to generate a test certificate or a self signed root CA.
  • newkey: This option creates a new certificate request and a new private key. The argument takes one of several forms. rsa:nbits, where nbits is the number of bits, generates an RSA key nbits in size.
  • nodes: If this option is specified then if a private key is created it will not be encrypted.
  • days: When the -x509 option is being used this specifies the number of days to certify the certificate for. The default is 30 days.
  • keyout: This gives the filename to write the newly created private key to.
  • out: This specifies the output filename to write to or standard output by default.

At this point you’ve got the key and associated certificate created with the desired subjectAltName property.

Add Certificate to Trusted Root Authority

When browsing a site with a self-signed cert, you will likely see something like this in the Chrome address bar:

Chrome & Insecure Certificate

Chrome & Insecure Certificate

This indicates there’s an issue with the certificate. Typically this is because the cert is not trusted by the computer. What you need to do is add it to the machine’s Trusted Root Authority.

  1. Within Chrome, do the following:

    1. Developer Tools » Security tab

    2. Click the View Certificate button to see the certificate:

      Chrome > Developer Tools > Security Tab > View Certificate

      Chrome > Developer Tools > Security Tab > View Certificate

    3. Click and drag the image to your desktop. It looks like a little certificate.

      Exporting the certificate

      Exporting the certificate

  2. Open the Keychain Access utility in OS X.

    1. Select the System option on the left.

    2. Click the lock icon in the upper-left corner to enable changes.

      Keychain > System

      Keychain > System

    3. In the lower left, select the Certificates option.

      Keychain Certificates

      Keychain Certificates

    4. Drag the certificate you copied to the desktop into the list of certificates.

    5. After localhost gets added to the System keychain, double-click it to open it again.

    6. Expand the Trust section and for the first option, pick Always Trust.

      Trusting Certificates

      Trusting Certificates

At this point everything has been configured. Quick Chrome and all other browsers and try again to navigate to the local HTTPS site. The browser should report it as a valid certificate:

Chrome & Trusted Certificate View

Chrome & Trusted Certificate View

At this point you now have a self-signed certificate installed on your machine.