[Originally posted on Slack Overflow, but comment thread complained about inappropriate venue.]
We're working on switching from StartCom SSL Certificates to Let's Encrypt, and trying to get it set up to automatically work with macOS Server + Apache HTTPD. From the command line tool (security import
), macOS Server doesn't accept the straight .pem
files—you have to give it a .p12
file, from which it extracts .pem
files to configure in Apache. Annoying and pointless, but it's what we have to live with for now.
In order to create this .p12
file, we have to execute this command:
openssl pkcs12 -export \
-inkey /etc/letsencrypt/live/example.com/privkey.pem \
-in /etc/letsencrypt/live/example.com/cert.pem \
-certfile /etc/letsencrypt/live/example.com/chain.pem \
-out /etc/letsencrypt/live/example.com/example.com.p12
And here's where it gets weird. The output example.com.p12
file has the example.com
certificate twice, followed by the Let's Encrypt intermediate CA certificate, followed by the unnecessary self-signed DST Root CA X3 anchor certificate (which all the browsers have installed in them by default), and finally followed by the private key. The result is that the Apache SSL handshake includes the server certificate twice, and the intermediate CA certificate, and the root certificate (which it should not be sending), which results in warnings on the Qualys SSL Labs tester.
We looked inside cert.pem
, and it only contains the server certificate (and only once). chain.pem
only contains the intermediate CA certificate (not the root anchor or the server cert). privkey.pem
only contains the private key. So openssl pkcs12 -export
is duplicating the server certificate and then going to the extra step of looking up the root anchor certificate and adding it.
If we run this same command on openSUSE Linux, the output .p12
file only has the server certificate (once), the intermediate CA certificate, and the private key. No root anchor.
We tried the following variations and saw no difference in output:
openssl pkcs12 -export \
-inkey /etc/letsencrypt/live/example.com/privkey.pem \
-in /etc/letsencrypt/live/example.com/fullchain.pem \
-out /etc/letsencrypt/live/example.com/example.com.p12
openssl pkcs12 -export \
-inkey /etc/letsencrypt/live/example.com/privkey.pem \
-certfile /etc/letsencrypt/live/example.com/fullchain.pem \
-out /etc/letsencrypt/live/example.com/example.com.p12
The only way I can duplicate the incorrect doubled server certificate behavior on a Linux machine is to do the following (but it still doesn't include the root anchor):
openssl pkcs12 -export \
-inkey /etc/letsencrypt/live/example.com/privkey.pem \
-in /etc/letsencrypt/live/example.com/cert.pem \
-certfile /etc/letsencrypt/live/example.com/fullchain.pem \
-out /etc/letsencrypt/live/example.com/example.com.p12
(Note the use of fullchain.pem
instead of chain.pem
in conjunction with the use of cert.pem
... makes perfect sense why the server cert would be duplicated, but that's not the command we're using on Mac OS X.)
Any idea how to get openssl pkcs12 -export
to do the right thing here?
OpenSSL 0.9.8zh 14 Jan 2016
isn't that old...openssl version
yieldsOpenSSL 0.9.8zh 14 Jan 2016
on my local computer running Sierra, but it actually yieldsLibreSSL 2.2.7
on the server on which this certificate script is running (High Sierra). So perhaps this is a bug in LibreSSL? I should update the title and tags, but first I'll test it on both tonight to see if the behavior is different.