Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer. You can expect quick tips, links to interesting tutorials, opinions and packages. Want to learn the cool stuff? Then sign up now!

Validating SSL certificates with PHP

With vanilla PHP it’s possible to check of if the SSL certificate of a given site is valid. But it’s kinda madness to do it. Let’s look at the code required:

// Step 1: downloading the certificate from the site $streamContext = stream_context_create([ 'ssl' => [ 'capture_peer_cert' => true, ], ]); $client = stream_socket_client( "ssl://spatie.be:443", $errorNumber, $errorDescription, $timeout, STREAM_CLIENT_CONNECT, $streamContext); $response = stream_context_get_params($client); $certificateProperties = openssl_x509_parse($response['options']['ssl']['peer_certificate']); // Step 2: parsing the certificate /* * I'm not even going to type out the further code needed. * * `$certificateProperties` has two keys `validFrom_time_t` and `validTo_time_t`. * Those keys contain the UTC representation of the date. * You will need to check if the current date is between those dates. */

What. The. Actual. F. Let’s fix this!

We’ve released a new package named spatie/ssl-certificate that makes checking the SSL certificate of a site laughably easy. Let’s take a look at the code:

$certificate = SslCertificate::createForHostName('spatie.be');
certificate->isValid(); // returns true if the certificate is currently valid

Boom, done.

The package has a few more methods that makes working with an SSL certificate a breeze:

$certificate->getIssuer(); // returns "Let's Encrypt Authority X3"

$certificate->getDomain(); // returns "spatie.be"

//A certificate can cover multiple (sub)domains. Here's how to get them.
$certificate->getAdditionalDomains(); // returns ["spatie.be", "www.spatie.be]

$this->certificate->validFromDate(); // returns an instance of Carbon

$certificate->getExpirationDate(); // returns an instance of Carbon

You can also use isValid to determine if a given domain is covered by the certificate. Of course it’ll keep checking if the current datetime is between validFromDate and expirationDate.

$this->certificate->isValid('spatie.be'); // returns true
$this->certificate->isValid('laravel.com'); // returns false

The source code of the package is available on GitHub. My company has made many more PHP framework agnostic, Laravel and JavaScript packages in the past. Take a look at the open source page at our site to see if we’ve made anything that could be of use to you.

Freek Van der Herten is a partner and developer at Spatie, an Antwerp based company that specializes in creating web apps with Laravel. After hours he writes about modern PHP and Laravel on this blog. When not coding he’s probably rehearsing with his kraut rock band. He loves waffles and butterflies.
  • Pingback: Freek Van der Herten: Validating SSL certificates with PHP – Asanka Rathnayake()

  • Would you mind giving a more concrete example of why you would use PHP to verify an SSL certificate? Is it for checking if a cert needs renewal (if so it seems a problem to let it expire first), or a problem with an SSL not having CA (pretty sure when interacting with CURL can handle this)?

    • René de Kat

      If, for example, you’re using a payment service and your application connects to the third party provider, you want to make sure you’re dealing with the correct folks, and not a man in the middle. A MIT attack that spoofs the DNS for example, so you’ll end up at a malicious server, which will have access to your very sensitive payment details.

      If you verify the peer first, which what you should always do, you can prevent sensitive data leakage. Also, when using CURL, NEVER disable verify_peer. Sometimes sandbox environments use invalid or self signed certificates. This is shite and the provider should use a proper one, but this is where you might consider it. This is tricky business though as you might forget to enable it for your production environment.

      • So this is for people not using CURL, or using CURL with verify_peer disabled?

        Thanks for the reply, I still don’t get it

    • I’ve mainly made this for use in another package I’m building that will monitor if the certificates on our own servers are still valid.

  • Pingback: Freek Van der Herten: Validating SSL certificates with PHP – SourceCode()

  • Pingback: August 2016 Newsletter - Nomad PHP()