mlocati / ocsp
使用在线证书状态协议(OCSP)查询HTTPS证书撤销状态的库
Requires
- php: >=5.5.9
- phpseclib/phpseclib: ^2 || ^3
Requires (Dev)
- ext-curl: *
- phpunit/phpunit: ^4.8.36 || ^5.7 || ^6.5 || ^7.4 || ^8.5.23 || ^9.5
README
在线证书状态协议PHP库
此存储库包含一个PHP库,帮助您通过在线证书状态协议(OCSP)检查HTTPS证书是否已撤销。
此库不需要对系统实用程序(如OpenSSL)的 exec
调用:它是一个纯PHP库。
此库不包含任何网络相关的助手:您必须使用自己的传输库(cURL、Zend HTTP、Guzzle等)。
检查HTTPS证书需要
- 要检查的证书,格式为PEM(即以 `-----BEGIN CERTIFICATE-----` 开头的文本文件),或DER格式(即二进制文件)
- 颁发者证书,即提供HTTPS证书的认证机构的证书
- 由认证机构提供的用于OCSP调用的URL(即所谓的
OCSR Responder URL
)
从HTTPS URL获取证书和颁发者证书
您可以使用以下代码从HTTPS URL获取HTTPS证书和颁发者证书
$hCurl = curl_init($url); curl_setopt($hCurl, CURLOPT_RETURNTRANSFER, false); curl_setopt($hCurl, CURLOPT_CUSTOMREQUEST, 'HEAD'); curl_setopt($hCurl, CURLOPT_NOBODY, true); curl_setopt($hCurl, CURLOPT_CERTINFO, true); curl_exec($hCurl); $certInfo = curl_getinfo($hCurl, CURLINFO_CERTINFO); $certificate = $certInfo[0]['Cert']; $issuerCertificate = $certInfo[1]['Cert'];
从证书获取颁发者证书
HTTPS证书通常包含一个URL,您可以在其中找到证书颁发者的证书。
您可以使用以下代码提取此URL,前提是 '/path/to/certificate'
是包含您的HTTPS证书的本地文件的路径
$certificateLoader = new \Ocsp\CertificateLoader(); $certificate = $certificateLoader->fromFile('/path/to/certificate'); $certificateInfo = new \Ocsp\CertificateInfo(); $urlOfIssuerCertificate = $certificateInfo->extractIssuerCertificateUrl($certificate);
此时,$urlOfIssuerCertificate
将包含可以从其中下载颁发者证书的URL(如果它是空字符串,则表示颁发者证书URL未包含在您的证书中)。
获取OCSP Responder URL
为了检查证书是否有效,我们需要知道由颁发证书的机构提供的URL,该URL可以用来检查证书是否已被撤销。
此URL可能包含在HTTPS证书本身中。
要获取它,您可以使用以下代码(前提是 '/path/to/certificate'
是包含您的HTTPS证书的本地文件的路径)
$certificateLoader = new \Ocsp\CertificateLoader(); $certificate = $certificateLoader->fromFile('/path/to/certificate'); $certificateInfo = new \Ocsp\CertificateInfo(); $ocspResponderUrl = $certificateInfo->extractOcspResponderUrl($certificate);
检查证书是否已被撤销
一旦您有了HTTPS证书、颁发者证书和OCSP Responder URL,您就可以检查HTTPS证书是否已被撤销,或者它是否仍然有效。
为此,您必须编写一些代码,如下所示(这里我们使用cURL,但您可以使用任何其他传输库)
$certificateLoader = new \Ocsp\CertificateLoader(); $certificateInfo = new \Ocsp\CertificateInfo(); $ocsp = new \Ocsp\Ocsp(); // Load the HTTPS certificate and the issuer certificate $certificate = $certificateLoader->fromFile('/path/to/certificate'); $issuerCertificate = $certificateLoader->fromFile('/path/to/issuer/certificate'); // Extract the relevant data from the two certificates $requestInfo = $certificateInfo->extractRequestInfo($certificate, $issuerCertificate); // Build the raw body to be sent to the OCSP Responder URL $requestBody = $ocsp->buildOcspRequestBodySingle($requestInfo); // Actually call the OCSP Responder URL (here we use cURL, you can use any library you prefer) $hCurl = curl_init(); curl_setopt($hCurl, CURLOPT_URL, $ocspResponderUrl); curl_setopt($hCurl, CURLOPT_RETURNTRANSFER, true); curl_setopt($hCurl, CURLOPT_POST, true); curl_setopt($hCurl, CURLOPT_HTTPHEADER, ['Content-Type: ' . \Ocsp\Ocsp::OCSP_REQUEST_MEDIATYPE]); curl_setopt($hCurl, CURLOPT_SAFE_UPLOAD, true); curl_setopt($hCurl, CURLOPT_POSTFIELDS, $requestBody); $result = curl_exec($hCurl); $info = curl_getinfo($hCurl); if ($info['http_code'] !== 200) { throw new \RuntimeException("Whoops, here we'd expect a 200 HTTP code"); } if ($info['content_type'] !== \Ocsp\Ocsp::OCSP_RESPONSE_MEDIATYPE) { throw new \RuntimeException("Whoops, the Content-Type header of the response seems wrong!"); } // Decode the raw response from the OCSP Responder $response = $ocsp->decodeOcspResponseSingle($result);
此时,$response
包含 Ocsp\Response
类的实例
- 如果
$response->isRevoked() === false
,则证书未被撤销 - 如果
$response->isRevoked() === true
,则证书已被撤销(您可以通过调用$response->getRevokedOn()
获取撤销的日期/时间) - 在未知状态下,
$response->isRevoked()
将返回null
异常
在加载证书、创建OCSP Responder请求体、分析OCSP Responder响应时可能会出现问题。为了捕获这些错误,您可以在代码中包围 try/catch 语句
try { // code } catch (\Ocsp\Exception\Exception $problem) { // handle the error cases }