The Nuts and Bolts of Setting Up SHA-1 and SHA-2 Certificates on OS X Server
As I described in the previous article in this series, one easy and straightforward approach to handling the transition from SHA-1 to SHA-2 certificates is to install a SHA-1 certificate as the main server certificate and individual SHA-2 certificates for each additional domain hosted on the server.
Starting with the job of choosing a certificate authority (CA), I’ll run through the mechanics of requesting and installing both SHA-1 and SHA-2 certificates. As I described in part two of this series, the idea is to provide SHA-1 to older browsers and SHA-2 to newer browsers — and to do so without jumping through too many hoops. (See “How to Deliver Both SHA-1 and SHA-2 Certificates With Your OS X Server”.) The approach I’ll describe is far from perfect, but it does a half-decent job of supporting older browsers without costing much in the way of effort.
Throughout what follows, I’ll assume a server which is set up in line with the suggestion from a much earlier article to separate your server domain from all your main websites. (See “At Last — Firing Up OS X Server”.) In the case of a server which is not set up that way — i.e., if the server’s main domain is providing an actual active website — then it’s important to consider the performance impact of installing a large-ish SAN certificate on an active site. I’ll touch on performance toward the end of this article.
Selecting a Certificate Authority
Plenty of CAs are available to choose from, and unfortunately for me I’ve used many different ones over the years at widely varying price points. I say “unfortunately” because it was only relatively recently that I decided to try StartCom.
There’s much to be said about StartCom, and much has been written about the pros and cons of a service that seems to elicit very strong reactions from almost everyone who has tried the Israeli company. What I will say is that for a small business looking for SAN and/or wildcard certificates at a reasonable price, there is virtually no other choice. There are free CAs which will provide certificates that work fine but are not trusted by default in major browsers. There are mainstream CAs which will provide SAN and wildcard certificates at prices ranging from hundreds to thousands of dollars. And then there’s StartCom, which is trusted by default in all major browsers and which charges only a relatively modest flat fee to verify identity, after which all certificates are free. For a small business looking for these types of certificates at a reasonable price, there is just no other choice.
On the downside, customers of StartCom must be prepared for a website inspired by Windows 95 — and which won’t tolerate the use of multiple browser tabs or multiple windows. They must be prepared to look the other way when they encounter the company’s quaintly out of date documentation, they must be prepared for the possibility of being insulted and even misdirected by the company’s support staff, and they must be prepared for nuisance security questions that at times become entirely pointless. (Yes, I have experienced entirely pointless security questions, such as being challenged to demonstrate ownership of a domain when requesting a new certificate, even though the company had just issued a certificate for the same domain only a few hours previously.) My suggestion is to suck it up, deal with the whackiness, and just get the best value possible from the service: prepare yourself to deal with it, and you’ll save potentially thousands of dollars.
In what follows, I won’t go into much detail about the mechanics of working with individual CAs, since it varies so widely.
Generating the CSR
The Server app makes it easy to generate a certificate signing request, or CSR: a wizard is available as “Get a Trusted Certificate” under certificate management. But as of Mavericks, anyway, the keys are created with SHA-1, meaning that the certificate which results will be SHA-1 as well. With Yosemite nearly upon us, and Apple’s 16 October event just one day away of this writing, it may be that this will soon change, and SHA-2 keys will be the default. (Nope, I haven’t tested the Yosemite version yet; I won’t be rushing to install it immediately on a production server anyway.) Either way, unless Server starts offering the option of selecting from either type of key from the GUI, it will be necessary to generate at least one set of keys from the command line.
This CSR will be provided to StartCom or whatever CA you happen to be using. It will be signed by the CA and the result returned to you as a certificate. Note that in the case of StartCom, it doesn’t actually matter what details are included in the various fields of the CSR: the resulting certificate will carry whatever details have been verified separately by StartCom, such as the name of the domain(s) and your address. In the case of other CAs, these details often do matter, so it’s essential to get them right if your CA requires it. Note also that in the case of StartCom, all certificates are free, so there is no price difference between ordinary, SAN, and wildcard certificates. Therefore, going back to the example SAN certificate I mentioned in the previous article in this series, you might choose a certificate that covers something like the following:
Assuming for the moment that you’re using a version of Server which generates SHA-1 keys, the main server certificate will be the only one we’ll install directly via the GUI. Dropping the resulting certificate file and any intermediates into the Server GUI to turn the greyed-out CSR into a fully functioning certificate couldn’t be easier. With the certificate installed via the GUI, it’s then straightforward to select “Custom…” from the “Secure services using” pop-up and set the new certificate to be used for the server’s default site.
It’s important not just to select the new certificate to secure all services on the server, but instead to specify that it be used only for the default website.
Now for the individual domain certificates, using SHA-2, we’ll move to the command line. To generate the CSR and private key for a domain named
test.local, we talk directly to
openssl like so:
openssl req -nodes -sha256 -newkey rsa:2048 -out test.local.csr -keyout test.local.key.pem
The resulting CSR can be submitted to a CA, just as with a CSR generated via the Server app itself — except that in this case, most CAs will sign using SHA-2 because the CSR itself uses SHA-2 as a result of the
-sha256 flag. Touching on the specifics of working with StartCom again, you may as well choose a wildcard certificate for each domain, like so:
(Note that should you want a new certificate at some point for the same domain, StartCom will not issue a new certificate with the same common name until shortly before an existing one expires. Worse, they charge a $25 to revoke an existing certificate. However, this limitation can easily be worked around simply by requesting a certificate with a slightly different common name — for example, by setting ‘www.domain1.com’ as the second entry and moving the wildcard to the third position.)
To import the private key, and later the certificate itself, into System keychain we again turn to the command line:
sudo security import /path/to/ssl.key -k "/Library/Keychains/System.keychain" -A
Note the use of the
-A flag here, which allows all apps to access the key: this mimics the behaviour of the Server app itself and enables the server actually to make use of the key. The same import command can be used to import the certificate, simply by replacing the path to the key with the path to the certificate. While the Keychain Access GUI can, in theory, be used to make the key available for all applications, in practice, this can wind up being far more hassle than it is worth due to permission issues, so I would suggest just using the flag during import. For the same reason, while the key can be imported via the GUI, permissions issues can again create hassles that just aren’t worth the effort when a single line via Terminal can do the same thing.
My own approach is actually to import the private key and the certificate into a local machine first, then re-export them in encrypted form using the Keychain Access GUI. That’s useful for the purpose of making a backup of the key and certificate, and it also makes it a little easier and more secure to import on the server, since there is just one file to import, and it is encrypted. Having a backup is important: lose the private key component, and the certificate becomes useless.
Finally, when importing an encrypted key, it turns out this normally must be done via screen sharing, because otherwise the process produces an error “SecKeychainItemImport: User interaction is not allowed.” due to the fact that a password is needed to interact with the System keychain. It is possible to use the
-P option to place an administrative password right on the command line in plain text. However, this puts the plain text password into the shell history; that could be cleaned up via
history -c, but it’s not at all optimal. (Why oh why is there no
-stdinpass, as in the case of other command line utilities like
hdiutil, which enables a password to be entered interactively from the command line over SSH?) The question ultimately is whether it is better to fire up screen sharing in order to avoid uploading an unencrypted key, or whether it’s better to put an unencrypted key on the server for a short time so it can be imported via SSH alone.
Either way, after importing, it’s fine to delete the key and certificate from the location where they were uploaded to the server prior to importing. Once imported, they’ll be stored in
/etc/certificates, and the private key will be encrypted.
After restarting Apache in the usual way, the certificate will now appear in the Server app, ready to be applied to the relevant site:
sudo apachectl graceful
There’s one last hitch with this process, which brings us to performance tuning.
HTTPS Performance and Cleaning Up Chain Bloat
There are many different aspects of HTTPS performance tuning which have been dealt with at microscopic levels of detail by many other people. Without going into all those, I will just mention two big and obvious ones.
First, under Mavericks, if you check the results of installing a new certificate using one of the testing tools like the server test at SSL Labs, you’ll immediately notice something screwy: OS X provides the entire certificate chain to browsers when setting up a TLS connection. (In fact, it’s even worse than this, with the server actually providing two copies of the certificate.) This is highly counterproductive: there is no need at all for the server to provide the root certificate to the browser while setting up the connection, and a browser should not trust any such root certificate even if it is provided. Instead, the CA’s root certificate will already be present in the browser’s trust store. The server should only provide the leaf certificate itself and the intermediate; bloating the chain with unusable extras risks overflowing the limited buffers available during the setup process and creating significant performance issues.
This can be avoided either by performing some manual tweaking or by running a script to complete the task. The problem is caused by OS X placing the entire chain into the
.chain.pem files stored in
/etc/certificates and then delivering both the contents of the full chain and the contents of the corresponding
.cert.pem files. For a certificate with an intermediate, this means OS X delivers a total of four different chunks: three from the chain file and one from the certificate file. It only needs to deliver two: one intermediate and one certificate. The fix is simple: edit the
.chain.pem file to contain nothing but the intermediate certificate, snipping out both the leaf and the root altogether. Restart Apache after this exercise, and presto — the SSL server test will show just two chunks of the chain being delivered by the server, exactly as it should be.
(Although this fix is very simple, it is also very tedious, especially if you have several certificates to install, and especially since it needs to be repeated every single time the system rebuilds the contents of
/etc/certificates, which occurs every time a certificate is added or deleted from the System keychain. In my own case, I use a simple script which runs through all certificate files, backs them up, cleans up the chains, and gets everything ready for use. If there’s interest, I may make this script available to other users.)
Last but not least, but also on the issue of chain size, there can be a significant performance impact from running a SAN certificate which contains a large number of separate domain names. Here, the problem isn’t having too many certificates in the chain, it’s the size of the SAN certificate itself: each additional domain name included in the certificate increases its size. As with adding superfluous root certificates or including multiple copies of leaf certificates, this can cause the certificate information that must be transmitted during connection setup to become so large that it cannot be completed in a single round trip between browser and server. This means that if you run a SAN as your server’s main certificate, and it includes a large number of separate domains, older browsers which don’t speak SNI will get a much slower connection to those separate domains than they would have if they were talking directly to a domain on a dedicated IP address with a smaller single-domain certificate. This fact also explains why it’s preferable to install an additional domain-specific certificate to protect anything else your server provides from its main domain, such as mail.
All material on this site is carefully reviewed, but its accuracy cannot be guaranteed, and some suggestions offered here might just be silly ideas. For best results, please do your own checking and verifying. This specific article was last reviewed or updated by Greg on .