Skip to content

Long-Term Validation

Pro — Commercial License Required
Long-Term Validation (LTV) memerlukan paket Pro.

LTV memastikan tanda tangan tetap bisa diverifikasi setelah sertifikat kedaluwarsa atau layanan revokasi offline dengan menyematkan semua data validasi ke dalam PDF melalui Document Security Store (DSS).

Class LTV

ClassTujuan
LtvManagerMengorkestrasi pembangunan chain, pengambilan OCSP/CRL, perakitan DSS
DssBuilderMembangun dictionary DSS dengan sertifikat, OCSP, CRL
OcspClientMengambil respons OCSP (RFC 6960)
CrlFetcherMengunduh CRL dari distribution point (RFC 5280)

LtvManager

Pada level B-LT atau B-LTA, LtvManager berjalan otomatis di dalam DigitalSigner. Untuk kontrol manual:

php
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(); // membangun dan menyematkan dictionary DSS

DssBuilder

Membangun dictionary DSS (ISO 32000-2) yang berisi /Certs, /OCSPs, /CRLs, dan entry /VRI per-tanda tangan opsional.

php
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 per-tanda tangan opsional
$dssDict = $dss->build();

OcspClient

Mengkueri responder OCSP untuk memeriksa status revokasi sertifikat.

php
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', // opsional; diekstrak dari AIA jika dihilangkan
);

echo $response->status();     // 'good', 'revoked', atau 'unknown'
echo $response->producedAt(); // DateTimeImmutable
$derBytes = $response->toDer();

CrlFetcher

Mengunduh CRL dari CDP yang dideklarasikan dalam sertifikat, dengan caching disk opsional.

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

$fetcher = new CrlFetcher();
$fetcher->cacheDir('/tmp/crl-cache');
$fetcher->cacheTtl(86400); // 24 jam

$crl = $fetcher->fetchForCertificate('/certs/signing.pem');
echo $crl->issuerDN();
echo $crl->revokedCount();
$crl->isRevoked('01:AB:CD:EF'); // bool
$derBytes = $crl->toDer();

Pembangunan Certificate Chain

LtvManager mengikuti extension AIA caIssuers untuk menemukan intermediate secara otomatis. Jika HTTP outbound dibatasi, berikan chain secara manual via CertificateInfo::chain().

php
$ltv = new LtvManager($pdf);
$ltv->buildChain(signerCertificate: '/certs/signing.pem');
$chain = $ltv->chain(); // array sertifikat yang di-encode DER

Archival Loop (B-LTA)

B-LTA menambahkan document timestamp setelah embedding DSS. Re-timestamp sebelum sertifikat TSA kedaluwarsa untuk mempertahankan validitas tanpa batas waktu:

Sign (B-B) -> TSA timestamp (B-T) -> DSS (B-LT) -> Document timestamp (B-LTA)
    -> [re-timestamp sebelum kedaluwarsa]
php
$ltv = LtvManager::load('/archive/contract-2026.pdf');
$ltv->retimestamp(new TsaClient('https://tsa.example.com/timestamp'));
$ltv->save('/archive/contract-2026.pdf');

Penanganan Error

Operasi LTV melempar exception bertipe: OcspException (responder tidak bisa dijangkau), CrlException (download gagal), atau ChainBuildException (chain tidak lengkap). Semuanya di bawah namespace Yeeefang\TcpdfNext\Pro\Security\Ltv.

Langkah Selanjutnya

Didistribusikan di bawah lisensi LGPL-3.0-or-later.