BLOG // June 1, 2021

Checking a remote hosts SSL expiry date with PHP

I recently had a requirement for a project to be able to check the SSL expiry date for remote websites using PHP. This simple function will return the number of days remaining on an SSL certificate, including potentially negative values if it's expired.

public static function sslDaysRemaining($url)
{
    $parsedUrl = parse_url($url, PHP_URL_HOST);
    $get = stream_context_create([
        "ssl" => [
            'capture_peer_cert' => true,
            'verify_peer' => false,
            'verify_peer_name' => false,
            'timeout' => 3
        ]
    ]);

    $read = stream_socket_client("ssl://".$parsedUrl.":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
    $cert = stream_context_get_params($read);

    $certificateInfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);

    $daysRemaining = (int)floor(($certificateInfo['validTo_time_t'] - time()) / 60 / 60 / 24);
    return $daysRemaining;
}

Using the openssl_x509_parse function you can actually get a lot more data than that. Below is an example for www.google.com:

Array
(
    [name] => /C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
    [subject] => Array
        (
            [C] => US
            [ST] => California
            [L] => Mountain View
            [O] => Google LLC
            [CN] => www.google.com
        )

    [hash] => 14dda233
    [issuer] => Array
        (
            [C] => US
            [O] => Google Trust Services
            [CN] => GTS CA 1O1
        )

    [version] => 2
    [serialNumber] => 0xFEDD8DC7EEF6EB49050000000087CC17
    [serialNumberHex] => FEDD8DC7EEF6EB49050000000087CC17
    [validFrom] => 210503112419Z
    [validTo] => 210726112418Z
    [validFrom_time_t] => 1620041059
    [validTo_time_t] => 1627298658
    [signatureTypeSN] => RSA-SHA256
    [signatureTypeLN] => sha256WithRSAEncryption
    [signatureTypeNID] => 668
    [purposes] => Array
        (
            [1] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => sslclient
                )

            [2] => Array
                (
                    [0] => 1
                    [1] =>
                    [2] => sslserver
                )

            [3] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => nssslserver
                )

            [4] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => smimesign
                )

            [5] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => smimeencrypt
                )

            [6] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => crlsign
                )

            [7] => Array
                (
                    [0] => 1
                    [1] => 1
                    [2] => any
                )

            [8] => Array
                (
                    [0] => 1
                    [1] =>
                    [2] => ocsphelper
                )

            [9] => Array
                (
                    [0] =>
                    [1] =>
                    [2] => timestampsign
                )

        )

    [extensions] => Array
        (
            [keyUsage] => Digital Signature
            [extendedKeyUsage] => TLS Web Server Authentication
            [basicConstraints] => CA:FALSE
            [subjectKeyIdentifier] => DB:77:7F:18:75:36:1E:7C:DF:DF:5D:D4:43:37:D2:6A:52:B2:41:57
            [authorityKeyIdentifier] => keyid:98:D1:F8:6E:10:EB:CF:9B:EC:60:9F:18:90:1B:A0:EB:7D:09:FD:2B

            [authorityInfoAccess] => OCSP - URI:http://ocsp.pki.goog/gts1o1core
CA Issuers - URI:http://pki.goog/gsr2/GTS1O1.crt

            [subjectAltName] => DNS:www.google.com
            [certificatePolicies] => Policy: 2.23.140.1.2.2
Policy: 1.3.6.1.4.1.11129.2.5.3

            [crlDistributionPoints] =>
Full Name:
  URI:http://crl.pki.goog/GTS1O1core.crl

            [ct_precert_scts] => Signed Certificate Timestamp:
    Version   : v1 (0x0)
    Log ID    : 44:94:65:2E:B0:EE:CE:AF:C4:40:07:D8:A8:FE:28:C0:
                DA:E6:82:BE:D8:CB:31:B5:3F:D3:33:96:B5:B6:81:A8
    Timestamp : May  3 12:24:20.476 2021 GMT
    Extensions: none
    Signature : ecdsa-with-SHA256
                30:45:02:20:4B:81:DA:A0:92:1D:B9:15:F4:4E:09:23:
                A2:CA:12:8E:33:4F:17:44:48:5B:AF:9A:DE:06:DE:D0:
                16:B2:3A:9B:02:21:00:93:A3:78:A2:7A:2D:0C:09:E6:
                A7:85:AA:7F:E4:D9:A2:A4:6B:72:33:D3:A6:4B:5E:92:
                37:34:F3:A6:E4:2B:27
Signed Certificate Timestamp:
    Version   : v1 (0x0)
    Log ID    : F6:5C:94:2F:D1:77:30:22:14:54:18:08:30:94:56:8E:
                E3:4D:13:19:33:BF:DF:0C:2F:20:0B:CC:4E:F1:64:E3
    Timestamp : May  3 12:24:20.414 2021 GMT
    Extensions: none
    Signature : ecdsa-with-SHA256
                30:46:02:21:00:A3:16:01:3D:F7:D8:3E:4E:D4:46:CA:
                4C:64:22:22:4B:A8:BC:82:C4:80:1C:A8:08:8D:80:3F:
                DC:C1:30:13:84:02:21:00:D0:D9:66:5C:29:75:42:C0:
                E7:53:A9:BC:A2:06:95:9F:3A:D4:E5:5A:D9:1F:C9:A2:
                6B:CB:B0:CE:6C:2F:18:D5
        )

)

As you can see there is a large amount of useful information available, and it can easily be scraped using PHP.

Comments

Subscribe to new articles

If you enjoy my content, consider subscribing. You will only receive new blog stories, no other email.