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.