Long-Term Validation
LTV đảm bảo chữ ký vẫn xác minh được sau khi chứng chỉ hết hạn hoặc dịch vụ thu hồi ngừng hoạt động bằng cách nhúng mọi dữ liệu validation vào PDF qua Document Security Store (DSS).
Class LTV
| Class | Mục đích |
|---|---|
LtvManager | Điều phối xây dựng chain, tải OCSP/CRL, tổ hợp DSS |
DssBuilder | Xây dựng dictionary DSS với cert, OCSP, CRL |
OcspClient | Tải OCSP response (RFC 6960) |
CrlFetcher | Tải CRL từ distribution point (RFC 5280) |
LtvManager
Tại cấp B-LT hoặc B-LTA, LtvManager chạy tự động bên trong DigitalSigner. Để kiểm soát thủ công:
use Yeeefang\TcpdfNext\Pro\Security\Ltv\LtvManager;
$ltv = new LtvManager($pdf);
$ltv->addCertificate(file_get_contents('/certs/intermediate.pem'));
$ltv->addCertificate(file_get_contents('/certs/root.pem'));
$ltv->addOcspResponse($ocspResponseDer);
$ltv->addCrl($crlDer);
$ltv->apply(); // xây dựng và nhúng dictionary DSSDssBuilder
Xây dựng dictionary DSS (ISO 32000-2) chứa /Certs, /OCSPs, /CRLs và entry /VRI tùy chọn theo chữ ký.
use Yeeefang\TcpdfNext\Pro\Security\Ltv\DssBuilder;
$dss = new DssBuilder();
$dss->addCertificate($intermediateDer);
$dss->addOcspResponse($ocspDer);
$dss->addCrl($crlDer);
$dss->addVri($sigHash, [$signerDer], [$ocspDer], [$crlDer]); // VRI tùy chọn theo chữ ký
$dssDict = $dss->build();OcspClient
Truy vấn OCSP responder để kiểm tra trạng thái thu hồi chứng chỉ.
use Yeeefang\TcpdfNext\Pro\Security\Ltv\OcspClient;
$ocsp = new OcspClient();
$ocsp->timeout(10);
$ocsp->cacheDir('/tmp/ocsp-cache');
$response = $ocsp->query(
certificate: '/certs/signing.pem',
issuer: '/certs/intermediate.pem',
responderUrl: 'https://ocsp.example.com', // tùy chọn; trích xuất từ AIA nếu bỏ qua
);
echo $response->status(); // 'good', 'revoked', hoặc 'unknown'
echo $response->producedAt(); // DateTimeImmutable
$derBytes = $response->toDer();CrlFetcher
Tải CRL từ CDP khai báo trong chứng chỉ, với cache đĩa tùy chọn.
use Yeeefang\TcpdfNext\Pro\Security\Ltv\CrlFetcher;
$fetcher = new CrlFetcher();
$fetcher->cacheDir('/tmp/crl-cache');
$fetcher->cacheTtl(86400); // 24 giờ
$crl = $fetcher->fetchForCertificate('/certs/signing.pem');
echo $crl->issuerDN();
echo $crl->revokedCount();
$crl->isRevoked('01:AB:CD:EF'); // bool
$derBytes = $crl->toDer();Xây dựng Certificate Chain
LtvManager theo extension AIA caIssuers để khám phá intermediate tự động. Nếu HTTP ra ngoài bị hạn chế, cung cấp chain thủ công qua CertificateInfo::chain().
$ltv = new LtvManager($pdf);
$ltv->buildChain(signerCertificate: '/certs/signing.pem');
$chain = $ltv->chain(); // mảng chứng chỉ mã hóa DERVòng lưu trữ (B-LTA)
B-LTA thêm document timestamp sau khi nhúng DSS. Re-timestamp trước khi chứng chỉ TSA hết hạn để duy trì hiệu lực vô thời hạn:
Ký (B-B) -> TSA timestamp (B-T) -> DSS (B-LT) -> Document timestamp (B-LTA)
-> [re-timestamp trước khi hết hạn]$ltv = LtvManager::load('/archive/contract-2026.pdf');
$ltv->retimestamp(new TsaClient('https://tsa.example.com/timestamp'));
$ltv->save('/archive/contract-2026.pdf');Xử lý lỗi
Thao tác LTV throw exception có kiểu: OcspException (responder không truy cập được), CrlException (tải thất bại), hoặc ChainBuildException (chain không đầy đủ). Tất cả nằm dưới namespace Yeeefang\TcpdfNext\Pro\Security\Ltv.
Bước tiếp theo
- Chữ ký số PAdES -- Tạo chữ ký ở mọi cấp PAdES.
- PDF/A-4 lưu trữ -- Kết hợp LTV với tuân thủ lưu trữ.
- Tích hợp HSM -- Ký dựa trên phần cứng với hỗ trợ LTV.