web-eid / ocsp-php
PHP 的 OCSP 库
Requires
- php: >=8.1
- phpseclib/phpseclib: 3.0.*
Requires (Dev)
- phpunit/phpunit: ^10.5
README
ocsp-php 是一个用于检查证书是否被撤销的 PHP 库,它通过使用在线证书状态协议 (OCSP) 实现。
此库不包含任何 HTTP 客户端,例如您可以使用 cURL。
快速入门
完成以下步骤以将库包含到您的项目中。
运行此快速入门需要使用 Composer 管理包的 PHP 网络应用程序。
将库添加到您的项目中
使用 Composer 安装
composer require web-eid/ocsp-php
加载证书
通过使用 CertificateLoader,您可以从文件或字符串中加载证书。
// Loading certificate from file $certificate = (new CertificateLoader)->fromFile('/path/to/cert.crt')->getCert(); // Loading certificate from string $certificate = (new CertificateLoader)->fromString('-----BEGIN CERTIFICATE-----MIIEAzCCA...-----END CERTIFICATE-----')->getCert();
从证书中获取发行者证书
证书通常包含一个 URL,您可以在其中找到证书发行者的证书。
您可以使用此代码从证书中提取此 URL。
$certLoader = (new CertificateLoader)->fromFile('/path/to/cert.crt'); $issuerCertificateUrl = $certLoader->getIssuerCertificateUrl();
$issuerCertificateUrl
将包含可以下载发行者证书的 URL。当它为空字符串时,表示发行者证书 URL 不包含在 SSL 证书中。
获取 OCSP 响应者 URL
要检查 SSL 证书是否有效,您需要知道 OCSP URL,这是由颁发证书的权威机构提供的。可以通过调用此 URL 来检查证书是否已被撤销。
此 URL 可能包含在 SSL 证书本身中。
您可以使用此代码从 SSL 证书中提取 OCSP 响应者 URL。
$certLoader = (new CertificateLoader)->fromFile('/path/to/cert.crt'); $ocspResponderUrl = $certLoader->getOcspResponderUrl();
当它为空字符串时,表示 OCSP 响应者 URL 不包含在 SSL 证书中。
检查 SSL 证书的撤销状态
一旦您有了 SSL 证书、发行者证书和 OCSP 响应者 URL,您就可以检查 SSL 证书是否已被撤销或仍然有效。
$subjectCert = (new CertificateLoader)->fromFile('/path/to/subject.crt')->getCert(); $issuerCert = (new CertificateLoader)->fromFile('/path/to/issuer.crt')->getCert(); // Create the certificateId $certificateId = (new Ocsp)->generateCertificateId($subjectCert, $issuerCert); // Build request body $requestBody = new OcspRequest(); $requestBody->addCertificateId($certificateId); // Add nonce extension when the nonce feature is enabled, // otherwise skip this line $requestBody->addNonceExtension(random_bytes(8)); // Send request to OCSP responder URL $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $ocspResponderUrl); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: ' .Ocsp::OCSP_REQUEST_MEDIATYPE]); curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody->getEncodeDer()); $result = curl_exec($curl); $info = curl_getinfo($curl); if ($info["http_code"] !== 200) { throw new RuntimeException("HTTP status is not 200"); } // Check the response content type if ($info["content_type"] != Ocsp::OCSP_RESPONSE_MEDIATYPE) { throw new RuntimeException("Content-Type header of the response is wrong"); } // Decode the raw response from the OCSP Responder $response = new OcspResponse($result); // Validate response certificateId $response->validateCertificateId($certificateId); // Validate response signature $response->validateSignature(); // Validate nonce when the nonce feature is enabled, $basicResponse = $response->getBasicResponse(); if ($requestBody->getNonceExtension() != $basicResponse->getNonceExtension()) { throw new RuntimeException("OCSP request nonce and response nonce do not match"); }
$response
包含 web_eid\ocsp_php\OcspResponse
类的实例
$response->isRevoked() === false
当证书未被撤销时$response->isRevoked() === true
当证书被撤销时(要获取撤销原因,请调用$response->getRevokeReason()
)- 当
$response->isRevoked()
返回 null 时,则证书撤销状态未知
要获取更多详细信息,可以使用
// Read response status $response->getStatus(); $basicResponse = $response->getBasicResponse();
以下方法可以与 $basicResponse
一起使用
$basicResponse->getResponses()
- 返回响应数组$basicResponse->getCertificates()
- 返回 X.509 证书数组 (phpseclib3\File\X509)$basicResponse->getSignature()
- 返回签名$basicResponse->getProducedAt()
- 返回 DateTime 对象$basicResponse->getThisUpdate()
- 返回 DateTime 对象$basicResponse->getNextUpdate()
- 返回 DateTime 对象(当nextUpdate
字段不存在时为null
)$basicResponse->getSignatureAlgorithm()
- 返回签名算法字符串(当签名算法未实现时抛出异常)$basicResponse->getNonceExtension()
- 返回 nonce(当值为null
时,表示响应中不存在 nonce 扩展)$basicResponse->getCertID()
- 返回响应证书ID
要获取完整的响应以进行调试或记录目的,请使用 $response->getResponse()
异常
所有异常都由 web_eid\ocsp_php\exceptions\OcspException
类处理。要捕获这些错误,您可以在代码中包含 try/catch 语句
try { // code } catch (OcspException $e) { // exception handler }
PHPSeclib 版本策略
从版本 1.1.0 开始,我们为 phpseclib
采用了灵活的版本策略,并将依赖指定为 3.0.*
。这种方法允许我们的库集成者快速整合来自 phpseclib
的安全补丁和次要更新。
为什么包含 composer.lock
虽然将 composer.lock
文件包含在应用程序中是锁定特定依赖版本的一种常见做法,但在库中这样做并不常见。然而,我们选择在我们的仓库中包含 composer.lock
,以清楚地指示我们已经测试过的依赖的确切版本。
尽管我们的库设计为可以与指定范围内的任何 phpseclib
次要版本一起工作,但 composer.lock
文件确保集成者知道我们认为稳定和安全的具体版本。提供的 composer.lock
旨在作为参考,而不是严格的要求。
代码格式化
我们使用 Prettier
进行代码格式化。要安装 Prettier,请使用以下命令
npm install --global prettier @prettier/plugin-php
运行代码格式化命令
composer fix-php
测试
在根目录中运行 phpunit 以运行所有单元测试。
./vendor/bin/phpunit tests