Adding a root certificate for PHP/OpenSSL on OSX

Nick Peirson
2 min readMar 30, 2016

--

OSX allows you to add and trust root certificates to the system keychain via a GUI or from a terminal. This is all well and good for most applications, e.g. browsers, but not all applications sing from the same hymn sheet. Even after adding our root certificate to the system keychain, PHP and OpenSSL were still giving me the following error:

php > file_get_contents(‘https://domain.signed.by.own.root.cert');Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in php shell code on line 1

It’s possible to get round this by disabling security checks, but then you may as well ditch the certificate entirely. After a bit of digging around I determined that this is because PHP isn’t aware of the system keychain and is instead looking at the following locations for certificates:

php > print_r(openssl_get_cert_locations());
Array
(
[default_cert_file] => /opt/local/etc/openssl/cert.pem
[default_cert_file_env] => SSL_CERT_FILE
[default_cert_dir] => /opt/local/etc/openssl/certs
[default_cert_dir_env] => SSL_CERT_DIR
[default_private_dir] => /opt/local/etc/openssl/private
[default_default_cert_area] => /opt/local/etc/openssl
[ini_cafile] =>
[ini_capath] =>
)

A little more digging turned up a process for exporting certificates from the system keychain and adding them to the certificate bundle installed for OpenSSL. If you’re following along at home you’ll need to replace the path to your certificate file in the below commands with the value from the ‘default_cert_file’ key from the command above.

$ sudo sh -c 'security find-certificate -a -p /Library/Keychains/System.keychain >> /opt/local/etc/openssl/cert.pem'
$ sudo sh -c 'security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> /opt/local/etc/openssl/cert.pem'

If your certificates are in a file and not already in the system keychain then you can simply concatenate the new root certificate onto the OpenSSL certificate bundle, e.g.

$ sudo sh -c 'cat /path/to/your/root/certificate >> /opt/local/etc/openssl/cert.pem'

You should now be able to access ‘https://domain.signed.by.own.root.cert’ from PHP without any errors and without having to disable any security checks.

--

--

Nick Peirson

Technical excellence in PHP and associated technologies