Creating Self-Signed Certificate Authority to issue SSL certificates using Certificate Assistant on macOS
Last Updated Aug 17, 2021
- Purpose
- Why Certificate Assistant and not easy-RSA or other PKI tools
- Why this blogpost, it was covered a million times on the Internet
- Creating Certificate Authority
- TLDR
- Walk-through
- Create Your Certificate Authority
- Certificate Information
- Key Pair Information for This CA
- Key Usage Extension For This CA:
- Key Usage Extension For Users of This CA:
- Extended Key Usage Extension For This CA
- Extended Key Usage For Users of This CA
- Basic Constraints Extension For This CA
- Basic Constraints Extension For Users fo This CA
- Subject Alternate Name Extension for This CA
Select Alternate Name for Users of This CA
- Specify a Location for the certificate
- Distributing Root CA to clients
- Creating certificate issued from this authority
- History
Purpose
Often devices that we use daily, such as raspberry pi hosted projects, UniFi controller, Firewall, NAS, etc, use SSL to secure communication but use self-signed certificates. While there is nothing wrong with the use of self-signed certificates per se, it is a bit annoying that you have to create security exceptions for each one on each of your user devices and despite that some vigilante browsers such as Chrome and Firefox still won’t be happy and would be displaying crossed-out the lock and claiming that the web site is not secure.
This is highly annoying, to say the least. There are two solutions to this inconvenience:
One - pay for commercial SSL DV (possibly wildcard) certificates and install them on all devices.
- Pros: browsers will be happy, nothing to configure on user devices.
- Cons: this costs money and wildcard certificates are even more expensive.
However, if only you and a bunch of other people are the only ones who use these devices services then there is no need to pay for a commercial certificate; Instead, you can create your own Certificate Authority, import it once to each device you use; set it to be trusted as Root CA and then keep issuing certificates from it to secure your devices.
- Pros: It’s completely free, and provides the same security and visuals.
- Cons: Because devices certificates are going to be issued from the CA that your systems know nothing about you would need to import the CA certificate and mark it as trusted explicitly on each device.
Now browsers will see that the certificates your devices and services use are non-self-signed anymore but use Certificate Authority that is trusted on your system and will happily show green lock. Voila.
Why Certificate Assistant and not easy-RSA or other PKI tools
Well, because it’s already there, it’s free, it is user-friendly, it stores certificates in your keychain by default, and just works. I think these are the reasons enough.
Why this blogpost, it was covered a million times on the Internet
Yes, it was, and yet every single tutorial and blogpost I found was missing some crucial details or was blatantly wrong. This blog post is an approach that worked for me and I successfully secured a bunch of appliances – such as UniFi controller and Synology DiskStation.
Creating Certificate Authority
TLDR
Follow the wizard with a few exceptions. Parts that are important to change or important to leave as is are in bold:
- Choose to Override Details,
- Disable extended key usage
Walk-through
- Start Keychain Access.app.
- Select Keychain Access -> Certificate Assistant -> Create Certificate Authority
Create Your Certificate Authority
Name
: Choose a friendly name for your CAIdentity type
: selectSelf Signed Root CA
User certificate
: Does not matter, we’ll delete it later.SSL Server
for now.Let me Override Defaults
: Check. Very important, you’ll see later why.Email from
: Select emailMake this CA as default
: Up to you.
Certificate Information
Serial Number
: Choose any number you like. I left it at 1.Validity Period (days)
: No longer than 825 daysCreate a CA web site
: Unchecked.Sign your invitation
: Uncheck
Press Continue
Email address
: Up to youName (Common Name)
: Select something telling, such as “My Home CA”Organization
,Unit
,City
,State
,Country
: Optional
Key Pair Information for This CA
Specify Key Pair Information For This CA
: 2048/RSA or longer
Press Continue
Specify Key Pair Information For Users of This CA
: 2048/RSA or longer
Press Continue
Key Usage Extension For This CA:
Include Key Usage Extensions
: CheckedThis extension is critical
: UncheckedCapabilities
:Signature
: CheckedCertificate Signing
: Checked
Key Usage Extension For Users of This CA:
Include Key Usage Extension
: CheckedThis Extension is Critical
: Checked- Capabilities
Signature
: CheckedKey Encipherment
: Checked
Extended Key Usage Extension For This CA
Include Extended Key Usage Extension
: Uncheck. In Catalina, this seems to be already unchecked by default.
This is to make Firefox happy. See more details here: https://bugzilla.mozilla.org/show_bug.cgi?id=1049176.
Extended Key Usage For Users of This CA
- Same as above, Uncheck.
Basic Constraints Extension For This CA
Include Basic Constraints Extension
: Checked- `Use this certificate as a certificate authority: Checked
Path Length Constraint Present
: Unchecked
Basic Constraints Extension For Users fo This CA
Include Basic Constraints Extension
: Unchecked
Subject Alternate Name Extension for This CA
Include Subject Alternate Name Extension
: Unchecked, Unless you have good reason to provide alternate names
Select Alternate Name for Users of This CA
Include Subject Alternate Name Extensions
: Unchecked, unless you have a good reason otherwise
Specify a Location for the certificate
You can decide to save your certificate authority to Login or System keychain. If you select System then before finalizing the certificate creation you would need to go back to the Keychain Access app, right-click on the System keychain and Unlock it. Otherwise, the certificate assistant will fail with an incomprehensible error message.
Keychain
: SystemTrust certificates signed by this CA on this machine
: Check
Now press Create
and provide your password a bunch of times - to import into the system keychain and to mark it as trusted.
Now we have the Certificate Authority. We can now issue certificates from it.
Distributing Root CA to clients
Export the CA certificate and distribute it to clients.
On a macOS
Double click the certificate to import it into Keychain. Find it there and mark as Trusted.
On Windows
See this post: https://stackoverflow.com/questions/23869177/import-certificate-to-trusted-root-but-not-to-personal-command-line
On iOS
AirDrop or mail yourself the certificate. Open it to install it. Then go to Settings
-> General
-> About
-> Certificate Trust Settings
and turn on Enable trust for that Root CA
Creating certificate issued from this authority
As an example, we will create and verify a certificate for a web server running in a docker container on the local machine. To facilitate this please add the following few hostnames to your /etc/hosts
file:
127.0.0.1 localtestserver
127.0.0.1 localtestserver.local
127.0.0.1 localtestserver.example.com
We will create a certificate that will be valid for these hostnames.
Walk-through
- Start Keychain Access
- Optionally, highlight the private key or certificate of the CA we created on the previews step
- Select Keychain Access -> Certificate Assistant -> Create a certificate
Create your certificate
Name
: Choose a name for your certificateIdentity Type
: change it to LeafCertificate Type
: SSL ServerLet me override defaults
: Check
Certificate information
Select Serial Number
: 1Validity Period
: 825 days or shorter
Note, for the certificates issued after June 2019 new requirements are in effect: https://support.apple.com/en-us/HT210176. This limits maximum validity to 825 days, amount other things.
Press Continue
Email
: up to youCommon name
: up to you
Choose an Issuer
Identity
: Select Certificate authority we have created on step one. Likely this will be the only one offered.
Key Pair Information
Leave at Defaults
Key Usage Extension
Leave at Defaults
Extended Key Usage
Extension is Critical
: CheckedSSL Server Authentication
: Checked
Basic Constraints
Leave at Defaults
Subject ALternate Name Extension
Include Subject Alternate Name Extension
: CheckedThis extension is critical
: Unchecked.- Extension Values
rfc822Name
: EmptyURI
: EmptyDNSName
: Specify space-separated list of hostnames:localtestserver localtestserver.local localtestserver.example.com
IPAddress
: 127.0.0.1
Specify the keychain
Does not matter. Complete the wizard.
Testing the certificate in a local webserver
Export keys
Open Keychain, search for a newly created certificate by hostname. You will see three entries: Certificate, Public key, and Private key.
- Select Certificate and export it to
certificate.cer
file. - Select Private Key and export it to
certificate.p12
file, with some pass-phrase.
Conver to plain-text
openssl x509 -inform der -in certificate.cer -out server.crt
openssl pkcs12 -in certificate.p12 -out server.key -nodes
You will be prompted for the private key pass-phrase (that you specified during an export on the previous step) by the second OpenSSL invocation. If you don’t want to type it in, you can specify it on a command line like so
openssl pkcs12 -in certificate.p12 -out server.key -nodes -password pass:Pa$$w0Rd
Starting apache in the docker
Install Docker. Then create Dockerfile
in the same directory where you have your keys with the following content:
FROM httpd:2.4
RUN sed -i \
-e 's/^#\(Include .*httpd-ssl.conf\)/\1/' \
-e 's/^#\(LoadModule .*mod_ssl.so\)/\1/' \
-e 's/^#\(LoadModule .*mod_socache_shmcb.so\)/\1/' \
conf/httpd.conf
RUN mkdir -p /usr/local/apache2/htdocs/public-html/ && \
echo "<html><body>It Works!</body></html>" > \
/usr/local/apache2/htdocs/public-html/index.html
COPY ./server.crt /usr/local/apache2/conf/server.crt
COPY ./server.key /usr/local/apache2/conf/server.key
This configures httpd container, turns on SSL extensions, and uploads our certificates into the right places. It also creates a simple HTML file that prints “It Works!”.
Now build and run your container:
docker build -t my-test-webserver-image .
docker run -itd \
-p 8080:80 \
-p 443:443 \
my-test-webserver-container
Then fire up Safari and and visit https://localtestmachine or https://localtestserver.local or https://localtestserver.example.com. You should be greeted with “It Works”. Click on the lock and confirm that the certificate is trusted and issued from your CA.
Note, you would need to import the CA certificate into the trusted root list in Firefox separately since it keeps a separate trust chain: Firefox -> Preferences -> Privacy and Security -> Certificates -> View Certificates -> Import…
History
February 26, 2019 | Initial publication |
November 27, 2019 | Updated to reflect new certificate requirements |
July 06, 2020 | Added advice to unlock the System keychain before importing the certificate. Fixed typos. Formatted hyperlinks. |
Aug 17, 2021 | Added missing extra step after “Extended Key Usage Extension For This CA”. Kudos to the reader who pointed this out. |