Skip to content

長期驗證(LTV)

Pro — Commercial License Required
長期驗證功能需要 Pro 套件。

長期驗證(Long-Term Validation)確保數位簽章在簽署者憑證過期或 CA 停止服務後仍然可以被驗證。Pro 套件將所有驗證所需資料嵌入 PDF 文件內,使文件具備自足的驗證能力。

核心類別

類別說明
LtvManagerLTV 流程協調器,自動執行完整的驗證資料嵌入
DssBuilder建構 Document Security Store(DSS)字典
OcspClient查詢 OCSP 回應以確認憑證狀態
CrlFetcher下載並解析憑證撤銷清單(CRL)

LtvManager

LtvManager 是最上層的協調器,自動完成 DSS 建構、驗證資料查詢與文件時間戳記。

php
use Yeeefang\TcpdfNext\Pro\Security\Ltv\LtvManager;
use Yeeefang\TcpdfNext\Pro\Security\Signature\DigitalSigner;
use Yeeefang\TcpdfNext\Pro\Security\Timestamp\TsaClient;

$tsa = new TsaClient('https://freetsa.org/tsr');

$signer = new DigitalSigner($cert);
$signer->level(SignatureLevel::PAdES_B_LTA);
$signer->timestampAuthority($tsa);

// 一行完成所有 LTV 流程
LtvManager::embed($pdf, $signer);

自訂 LTV 選項

php
LtvManager::embed($pdf, $signer, [
    'includeOcsp' => true,       // 嵌入 OCSP 回應(預設 true)
    'includeCrl'  => true,       // 嵌入 CRL(預設 true)
    'ocspTimeout' => 10,         // OCSP 查詢逾時(秒)
    'crlTimeout'  => 30,         // CRL 下載逾時(秒)
    'retryCount'  => 3,          // 重試次數
]);

DssBuilder

DSS(Document Security Store)是 PDF 2.0 定義的機制,將憑證、OCSP 回應與 CRL 集中儲存在文件層級。

php
use Yeeefang\TcpdfNext\Pro\Security\Ltv\DssBuilder;

$dss = DssBuilder::create()
    ->addCertificate($caCert)
    ->addCertificate($intermediateCert)
    ->addOcspResponse($ocspResponse)
    ->addCrl($crlData);

$pdf->setDss($dss->build());

驗證相關資訊(VRI)

每個簽章都有對應的 VRI(Validation Related Information)條目,以簽章雜湊值為鍵:

php
$dss->addVri(
    signatureHash: 'A1B2C3D4...',
    certificates: [$signerCert, $caCert],
    ocspResponses: [$ocspResponse],
    crls: [$crlData],
    timestamp: $tsToken
);

VRI 讓驗證器能夠精確找到每個簽章所需的驗證資料,而不需掃描整個 DSS。

OcspClient

OCSP(Online Certificate Status Protocol)用於即時查詢憑證的撤銷狀態。

php
use Yeeefang\TcpdfNext\Pro\Security\Ltv\OcspClient;

$ocsp = new OcspClient();
$ocsp->setTimeout(seconds: 10);
$ocsp->setRetryCount(3);

$response = $ocsp->query(
    certificate: $signerCert,
    issuerCertificate: $caCert,
    responderUrl: 'http://ocsp.example.com'
);

if ($response->isGood()) {
    echo "憑證狀態:有效\n";
    echo "下次更新:{$response->nextUpdate()->format('Y-m-d')}\n";
} elseif ($response->isRevoked()) {
    echo "憑證已撤銷:{$response->revocationTime()->format('Y-m-d')}\n";
}

自動探索 OCSP 端點

如果未手動指定端點,OcspClient 會自動從憑證的 Authority Information Access(AIA)擴充欄位擷取 OCSP 回應端點。

php
$url = $ocsp->discoverResponder($signerCert);
// 回傳如 'http://ocsp.example.com/responder'

CrlFetcher

CRL(Certificate Revocation List)是 CA 定期發布的憑證撤銷清單,作為 OCSP 的備援機制。

php
use Yeeefang\TcpdfNext\Pro\Security\Ltv\CrlFetcher;

$fetcher = new CrlFetcher();
$fetcher->setTimeout(seconds: 30);

$crlData = $fetcher->fetch('http://crl.example.com/ca.crl');

// 檢查 CRL 是否仍在有效期內
if ($fetcher->isExpired($crlData)) {
    $crlData = $fetcher->fetch($crlUrl, forceRefresh: true);
}

自動探索 CRL 端點

php
$urls = $fetcher->discoverDistributionPoints($signerCert);
// 回傳如 ['http://crl.example.com/ca.crl']

歸檔迴圈

當驗證資料(OCSP 回應或 CRL)即將過期時,可以執行歸檔迴圈來更新驗證資料並加入新的文件時間戳記:

php
// 針對已簽署的文件執行歸檔迴圈
$pdf = Document::open('/output/signed-blta.pdf');

LtvManager::archivalLoop($pdf, [
    'tsaUrl'   => 'https://freetsa.org/tsr',
    'refresh'  => true,    // 重新查詢 OCSP/CRL
]);

$pdf->save('/output/signed-blta-refreshed.pdf');

歸檔迴圈以增量更新方式附加新的驗證資料與文件時間戳記,不會破壞既有的簽章。這個流程可以定期排程執行,確保文件的驗證能力在數十年後仍然有效。

下一步

以 LGPL-3.0-or-later 授權釋出。