web-eid/ocsp-php

PHP 的 OCSP 库

1.1.2 2024-03-15 11:51 UTC

This package is auto-updated.

Last update: 2024-09-27 08:27:22 UTC


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