Lewati ke konten
getnextpdf.com

Enterprise edisi

Validasi tanda tangan secara batch

NextPDF Enterprise memvalidasi tanda tangan digital pada banyak dokumen PDF dalam satu panggilan. NextPDF\Enterprise\Signature\BatchSignatureValidator::validate() menerima daftar dokumen dan mengembalikan sebuah BatchValidationReport. Setiap tanda tangan melewati pipeline fail-closed yang sama: autentikasi CMS kriptografis atas rentang byte yang ditandatangani, validasi certificate-chain berbasis trust anchor, dan pemeriksaan pencabutan OCSP/CRL. Laporan tersebut membawa detail per-dokumen dan per-tanda tangan — CertChainStatus, RevocationStatus, TimestampStatus — sehingga tooling kepatuhan dapat menurunkan kembali setiap verdict dari bukti yang tercatat.

Model verdict-nya sengaja dibuat ketat. Sebuah tanda tangan Valid hanya ketika semua bukti tegas dibuktikan. Bukti pencabutan yang hilang menghasilkan Indeterminate, bukan Valid. Halaman ini membahas orkestrator batch dan tipe hasilnya. Sisi verifikasi AdES untuk dokumen tunggal didokumentasikan di Verifikasi tanda tangan. Penyematan material validasi jangka panjang didokumentasikan di Archive.

Kapabilitas ini disertakan dalam NextPDF Enterprise (nextpdf/enterprise) dan diaktifkan dengan envelope lisensi tier Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.

Terminal window
composer require nextpdf/enterprise

Metapaket nextpdf/premium juga meresolusi paket Enterprise. Aktivasi menggunakan envelope lisensi Enterprise Anda; lihat Lisensi dan aktivasi. Tipe-tipe batch di-autoload di bawah NextPDF\Enterprise\Signature. Tidak ada ekstensi PHP di luar baseline engine yang diperlukan.

Satu panggilan ke validate() memproses daftar nilai DocumentSignatureInput. Setiap input membawa identifier dokumen, byte PDF mentah, dan trust anchor berformat PEM opsional. Validator mengekstrak dictionary tanda tangan setiap dokumen dan menjalankan tiga tahap per tanda tangan.

Tahap 1 — autentikasi kriptografis. Blob CMS/PKCS#7 detached dari /Contents diverifikasi atas byte yang dicakup oleh /ByteRange. Verifier menghitung ulang digest konten itu sendiri dan membandingkannya dengan atribut bertanda tangan messageDigest. Verifier tidak pernah mempercayai digest yang disediakan oleh produser (RFC 5652 §5.6). Nilai tanda tangan harus terverifikasi, dan sertifikat penanda tangan harus terikat pada CMS. /Contents atau /ByteRange yang tidak ada atau salah bentuk, CMS yang tidak dapat diurai, ketidakcocokan digest, atau pemeriksaan tanda tangan yang gagal semuanya fail closed. Sebuah tanda tangan yang terverifikasi di bawah SHA-1 diperlakukan sebagai lemah dan tidak pernah menjadi lulus penuh.

Tahap 2 — validasi chain dan trust anchoring. Chain penanda tangan yang dipulihkan dari CMS divalidasi sebagai calon jalur sertifikasi. trustedCerts yang Anda sediakan adalah input trust anchor, dalam pengertian RFC 5280 §6.1.1: terminus chain harus cocok dengan anchor yang disediakan berdasarkan fingerprint DER SHA-256. Sebuah chain yang konsisten secara struktural namun terminusnya bukan anchor yang dikonfigurasi tidak pernah dilaporkan sebagai trusted. Tanpa anchor yang dapat digunakan, hanya verdict struktural yang dilaporkan, dan CertChainStatus::$trusted tetap false.

Tahap 3 — pencabutan. Pencabutan berjalan atas chain yang dipulihkan setelah autentikasi, mencerminkan model ETSI EN 319 102-1 di mana pemeriksaan pencabutan mengikuti validasi jalur yang berhasil (clause 5.2.6.2). OCSP adalah primer: hanya respons yang terverifikasi secara kriptografis yang diperhitungkan, sebagai Good atau Revoked. Jalur CRL adalah fallback dan mengatestasi kesegaran daftar. Ketika tidak ada klien yang dikonfigurasi, statusnya adalah unavailable.

Verdict per-tanda tangan adalah sebuah SignatureValidationStatus. Taksonominya mencerminkan model status ETSI EN 319 102-1 (TOTAL-PASSED / TOTAL-FAILED / INDETERMINATE) pada granularitas per-tanda tangan:

BuktiVerdict
Sertifikat dikonfirmasi tercabutInvalid (menentukan, terlepas dari pemeriksaan lain)
Autentikasi CMS gagal, tidak ada material penanda tangan yang dipulihkanError
Autentikasi CMS gagal, material penanda tangan adaInvalid
Terautentikasi, tetapi chain tidak tervalidasiInvalid (atau Error tanpa chain)
Terautentikasi dan chain valid, tetapi tidak ada trust anchor yang dikonfirmasiIndeterminate
Terautentikasi, chain valid, trusted, tetapi tidak ada non-pencabutan yang konklusifIndeterminate
Semua hal di atas tegas dibuktikanValid

Aturan non-pencabutan yang konklusif. “Tidak terbukti tercabut” tidak sama dengan “terbukti tidak tercabut”. Verdict Valid memerlukan setidaknya satu hasil pencabutan Good. Respons OCSP yang terverifikasi baik adalah bentuk konklusif: ia menegaskan status sertifikat penanda tangan itu sendiri. Sebuah CRL yang diterima secara kriptografis dan segar juga memenuhi gate dalam implementasi ini, tetapi hanya sebagai atestasi kesegaran-dan-integritas — jalur tersebut tidak mengurai entri per-serial, sehingga tidak memberikan jaminan pencabutan per-serial dan tidak pernah verdict revoked yang positif. Konfigurasikan OCSP di mana pun deteksi pencabutan positif penting: deployment yang hanya CRL tidak akan memunculkan sertifikat yang tercabut sebagai Invalid. Ketika hasil OCSP dan CRL keduanya Unknown atau Unavailable, status pencabutan tidak dapat ditentukan, dan verdict-nya adalah Indeterminate. Ini mengikuti ETSI EN 319 102-1: informasi status pencabutan yang tidak tersedia menghasilkan INDETERMINATE, bukan lulus (clause 5.1.3, TRY_LATER). Ini adalah pengetatan perilaku pada 3.1.0 dengan dampak kompatibilitas mundur: rilis sebelumnya dapat melaporkan Valid tanpa bukti pencabutan yang konklusif. Deployment yang tidak mengonfigurasi klien OCSP atau CRL kini umumnya melihat Indeterminate di tempat mereka sebelumnya melihat Valid.

Dua batasan membingkai kapabilitas ini secara jujur. Pertama, validator batch tidak mengevaluasi token timestamp yang disematkan: TimestampStatus dalam hasil batch selalu berupa keadaan absent. Evaluasi timestamp RFC 3161 adalah milik sisi verifikasi dokumen tunggal; lihat Verifikasi tanda tangan. Kedua, halaman ini adalah validasi baca-saja. Penyematan material DSS/VRI untuk validitas jangka panjang adalah kapabilitas Archive.

Keputusan yang menjadi tumpuan adalah produser verdict yang fail-closed. Valid hanya dicetak dari bukti tegas pada ketiga sumbu: autentikasi kriptografis, chain berbasis trust anchor, dan non-pencabutan yang konklusif. Apa pun yang tidak terbukti terdegradasi menjadi Indeterminate alih-alih default ke lulus, yang merupakan sikap EN 319 102-1 untuk material pencabutan yang hilang. Throughput batch tidak pernah membeli kembali kekakuan: lapisan batch adalah orkestrasi atas verifier CMS teraudit yang sama yang digunakan untuk dokumen tunggal, sehingga run 1.000 dokumen menerapkan kriptografi yang identik. Laporan juga memisahkan bukti dari verdict — CertChainStatus dan RevocationStatus mencatat input yang menjadi dasar setiap verdict, sehingga auditor dapat menurunkannya kembali nanti.

Latar belakang desain: Signing at scale, without compromise.

Semua simbol di bawah ini adalah API publik dalam nextpdf/enterprise 3.1.0.

final class BatchSignatureValidator
{
public function __construct(
?SignatureExtractor $extractor = null,
?CertificateChainValidator $chainValidator = null,
private readonly ?OcspClient $ocspClient = null,
private readonly ?CrlFetcher $crlFetcher = null,
?CmsSignatureDataExtractor $cmsExtractor = null,
private readonly ClockInterface $clock = new SystemClock(),
)
public function validate(array $inputs): BatchValidationReport
}

Melempar atau gagal dengan: validate() melempar \InvalidArgumentException jika daftar input kosong, dan \OverflowException ketika batch melebihi 1.000 dokumen. Sebuah dokumen yang bukan PDF yang dapat diurai tidak melempar; ia menjadi hasil Error per-dokumen. $clock adalah Psr\Clock\ClockInterface PSR-20 yang digunakan untuk keputusan kesegaran CRL, sehingga verdict bersifat deterministik di bawah test clock yang dibekukan.

final readonly class DocumentSignatureInput
{
public string $documentId;
public function __construct(
string $documentId,
public string $pdfData,
public array $trustedCerts = [],
)
}

Melempar atau gagal dengan: \InvalidArgumentException jika $documentId adalah string kosong. $trustedCerts adalah daftar sertifikat trust anchor berformat PEM.

final readonly class BatchValidationReport
{
public function __construct(
public array $documents,
public int $totalDocuments,
public int $totalSignatures,
public int $totalValid,
public int $totalInvalid,
public float $durationMs,
)
public function allValid(): bool
public function hasDocumentsWithoutSignatures(): bool
public function toJson(?CertPiiGuard $piiGuard = null): string
}

Melempar atau gagal dengan: toJson() melempar \JsonException jika encoding gagal. allValid() bernilai true hanya ketika terdapat tanda tangan dan tidak ada satu pun yang non-valid. Secara default toJson() menerapkan NextPDF\Enterprise\Signature\Eidas\CertPiiGuard yang privacy-by-default, yang menyamarkan nama penanda tangan, root issuer, nama TSA, dan diagnostik masalah chain; lihat Tingkat jaminan eIDAS untuk API guard tersebut.

DocumentValidationResult dan DocumentValidationStatus

Bagian berjudul “DocumentValidationResult dan DocumentValidationStatus”
final readonly class DocumentValidationResult
{
public function __construct(
public string $documentId,
public DocumentValidationStatus $status,
public array $signatures,
public int $validCount,
public int $invalidCount,
)
public function hasSignatures(): bool
public function totalSignatures(): int
}
enum DocumentValidationStatus: string
{
case AllValid = 'all_valid';
case SomeInvalid = 'some_invalid';
case AllInvalid = 'all_invalid';
case NoSignatures = 'no_signatures';
case Error = 'error';
}

Melempar atau gagal dengan: tidak ada. Value object yang immutable dan backed enum.

SignatureValidationResult dan SignatureValidationStatus

Bagian berjudul “SignatureValidationResult dan SignatureValidationStatus”
final readonly class SignatureValidationResult
{
public function __construct(
public SignatureValidationStatus $status,
public CertChainStatus $certChain,
public TimestampStatus $timestamp,
public RevocationStatus $revocation,
public string $signer,
public string $level = '',
public string $subFilter = '',
public string $reason = '',
)
public function isValid(): bool
}
enum SignatureValidationStatus: string
{
case Valid = 'valid';
case Invalid = 'invalid';
case Indeterminate = 'indeterminate';
case Error = 'error';
}

Melempar atau gagal dengan: tidak ada. $signer adalah subjek sertifikat yang terverifikasi CMS ketika autentikasi lulus, jika tidak maka string kosong. $level adalah label yang diturunkan dari SubFilter (misalnya B-B untuk ETSI.CAdES.detached), bukan penetapan konformansi AdES.

final readonly class CertChainStatus
{
public function __construct(
public bool $valid,
public bool $trusted,
public int $chainLength,
public string $rootIssuer,
public array $issues = [],
)
public function hasIssues(): bool
}

Melempar atau gagal dengan: tidak ada. $trusted disetel hanya pada kecocokan keanggotaan trust anchor yang dikonfirmasi, tidak pernah dari ketidak-kosongan daftar anchor.

final readonly class RevocationStatus
{
public function __construct(
public RevocationCheckResult $ocspStatus,
public RevocationCheckResult $crlStatus,
public bool $isRevoked,
public ?DateTimeImmutable $revocationDate = null,
)
public static function unavailable(): self
public function hasConclusiveGood(): bool
}
enum RevocationCheckResult: string
{
case Good = 'good';
case Revoked = 'revoked';
case Unknown = 'unknown';
case Unavailable = 'unavailable';
}

Melempar atau gagal dengan: tidak ada dari anggota yang ditampilkan. Kelas ini juga memaparkan factory statis yang diperiksa-bukti (good(), revoked(), fromResults()), yang melempar \InvalidArgumentException ketika status yang diklaim bertentangan dengan bukti OCSP/CRL — hasil tercabut tidak pernah dapat dicetak sebagai tidak-tercabut, atau sebaliknya. hasConclusiveGood() bernilai true hanya untuk status tidak-tercabut di mana setidaknya satu pemeriksaan bernilai Good.

final readonly class TimestampStatus
{
public function __construct(
public bool $present,
public bool $valid,
public ?DateTimeImmutable $timestampTime = null,
public string $tsaName = '',
public array $issues = [],
)
public static function absent(): self
}

Melempar atau gagal dengan: tidak ada. Dalam hasil batch ini selalu berupa keadaan absent(); lihat Kasus tepi & jebakan.

Validasi satu dokumen dan baca laporannya. Contoh ini menggunakan PDF yang tidak ditandatangani, sehingga output-nya deterministik.

batch-quick-start.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Signature\BatchSignatureValidator;
use NextPDF\Enterprise\Signature\DocumentSignatureInput;
// A minimal, unsigned PDF: the validator reports it as no_signatures.
$unsigned = "%PDF-1.7\n1 0 obj\n<< /Type /Catalog >>\nendobj\ntrailer\n<< /Root 1 0 R >>\n%%EOF\n";
$validator = new BatchSignatureValidator();
try {
$report = $validator->validate([
new DocumentSignatureInput(documentId: 'doc-001', pdfData: $unsigned),
]);
} catch (\InvalidArgumentException $e) {
// Empty input list, or an empty documentId.
echo 'Rejected: ' . $e->getMessage() . "\n";
exit(1);
}
echo 'Documents: ' . $report->totalDocuments . "\n";
echo 'Signatures: ' . $report->totalSignatures . "\n";
foreach ($report->documents as $doc) {
echo $doc->documentId . ': ' . $doc->status->value . "\n";
}
echo 'All valid: ' . ($report->allValid() ? 'yes' : 'no') . "\n";
echo 'Unsigned documents: ' . ($report->hasDocumentsWithoutSignatures() ? 'yes' : 'no') . "\n";

Output yang diharapkan:

Documents: 1
Signatures: 0
doc-001: no_signatures
All valid: no
Unsigned documents: yes

Perhatikan bahwa allValid() melaporkan no di sini: ia memerlukan setidaknya satu tanda tangan dan tidak ada hasil non-valid, sehingga himpunan tanda tangan yang kosong tidak pernah lulus secara diam-diam.

Validasi sebuah direktori kontrak yang ditandatangani dengan klien pencabutan, trust anchor, chunking batch, dan laporan JSON yang terlindungi PII.

batch-validate-contracts.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Ltv\CrlFetcher;
use NextPDF\Enterprise\Security\Ltv\OcspClient;
use NextPDF\Enterprise\Security\Ltv\OcspResponseCache;
use NextPDF\Enterprise\Signature\BatchSignatureValidator;
use NextPDF\Enterprise\Signature\DocumentSignatureInput;
use NextPDF\Enterprise\Signature\SignatureValidationStatus;
// Any PSR-18 client works; Guzzle shown here.
$httpClient = new \GuzzleHttp\Client(['timeout' => 10]);
// Revocation clients make a conclusive non-revoked (Good) result reachable.
// Without them, every verdict tops out at Indeterminate. The response cache
// lets repeat signers across the batch resolve without extra network calls.
$validator = new BatchSignatureValidator(
ocspClient: new OcspClient($httpClient, cache: new OcspResponseCache()),
crlFetcher: new CrlFetcher($httpClient),
);
// Trust anchors are an input: the chain terminus must match one of these.
$anchors = [(string) file_get_contents('/etc/nextpdf/trust/enterprise-root.pem')];
$inputs = [];
foreach (glob('/var/contracts/signed/*.pdf') ?: [] as $path) {
$inputs[] = new DocumentSignatureInput(
documentId: basename($path),
pdfData: (string) file_get_contents($path),
trustedCerts: $anchors,
);
}
$exit = 0;
// One call is capped at 1,000 documents; chunk larger runs.
foreach (array_chunk($inputs, 1000) as $batch) {
try {
$report = $validator->validate($batch);
// Signer PII is redacted by default in the serialized report.
file_put_contents('/var/log/nextpdf/batch-report.jsonl', $report->toJson() . PHP_EOL, FILE_APPEND); // one JSON document per line
} catch (\InvalidArgumentException | \OverflowException $e) {
fwrite(STDERR, 'Batch rejected: ' . $e->getMessage() . "\n");
exit(2);
} catch (\JsonException $e) {
fwrite(STDERR, 'Report encoding failed: ' . $e->getMessage() . "\n");
exit(3);
}
foreach ($report->documents as $doc) {
foreach ($doc->signatures as $sig) {
if ($sig->status !== SignatureValidationStatus::Valid) {
$exit = 1;
fwrite(STDERR, sprintf(
"%s: %s (chain trusted: %s, revoked: %s)\n",
$doc->documentId,
$sig->status->value,
$sig->certChain->trusted ? 'yes' : 'no',
$sig->revocation->isRevoked ? 'yes' : 'no',
));
}
}
}
}
exit($exit);

Output yang diharapkan (stderr, untuk satu dokumen yang bukti pencabutannya tidak tersedia; baris lain bervariasi sesuai input Anda):

contract-0042.pdf: indeterminate (chain trusted: yes, revoked: no)

Laporan JSON menserialisasi field identitas penanda tangan melalui CertPiiGuard default, sehingga entri per-tanda tangan tampak seperti ini (kutipan, ilustratif):

{
"status": "indeterminate",
"signer": "[REDACTED]",
"level": "B-B",
"subFilter": "ETSI.CAdES.detached"
}
  • Daftar input kosong melempar \InvalidArgumentException; lebih dari 1.000 dokumen dalam satu panggilan melempar \OverflowException. Bagi run yang lebih besar menjadi chunk, seperti pada contoh produksi.
  • Meng-upgrade dari rilis sebelumnya: tanpa klien OCSP atau CRL yang dikonfigurasi, pencabutan bernilai unavailable, sehingga tidak ada tanda tangan yang dapat mencapai Valid. Rilis sebelumnya melaporkan Valid di sini; 3.1.0 melaporkan Indeterminate (lihat Gambaran konseptual).
  • Penghitung tingkat-dokumen bersifat ketat: hanya Valid yang menambah validCount. Invalid, Indeterminate, dan Error semuanya menambah invalidCount. Sebuah dokumen yang satu-satunya tanda tangannya adalah Indeterminate karena itu melaporkan all_invalid. Gunakan gate pada status per-tanda tangan ketika perbedaannya penting.
  • Pemeriksaan OCSP berjalan hanya ketika chain yang dipulihkan memiliki setidaknya dua sertifikat, karena query memerlukan issuer. Chain dengan sertifikat tunggal jatuh ke jalur CRL atau unavailable.
  • crlStatus tidak pernah melaporkan revoked dalam hasil batch. Fallback CRL hanya mengatestasi kesegaran daftar; hasil tercabut yang otoritatif berasal dari OCSP.
  • timestamp selalu absent() dalam hasil batch. Validator batch tidak mengevaluasi token RFC 3161 yang disematkan; gunakan Verifikasi tanda tangan untuk evaluasi timestamp.
  • signer kosong ketika autentikasi gagal. Ketika disetel, ia adalah CN subjek (atau O) dari sertifikat yang terverifikasi CMS — tidak pernah string /Name yang tidak terautentikasi dari dictionary tanda tangan.
  • Entri trustedCerts harus berupa sertifikat PEM. Daftar anchor yang kosong atau salah bentuk menghasilkan verdict chain struktural-saja dengan trusted: false, membatasi verdict pada Indeterminate.
  • Byte yang tidak diawali dengan header PDF menghasilkan status error per-dokumen dengan nol tanda tangan — tanpa exception.
  • toJson() meredaksi PII secara default. Berikan new CertPiiGuard(disclosePii: true) hanya di tempat Anda memegang dasar hukum yang terdokumentasi untuk memproses identitas penanda tangan.
  • Produser verdict yang fail-closed. Valid memerlukan semua hal berikut: autentikasi CMS yang terverifikasi atas digest /ByteRange, chain yang valid, keanggotaan trust anchor yang dikonfirmasi, dan status tidak-tercabut yang konklusif. Setiap pemeriksaan yang tidak terbukti mendegradasi verdict; tidak ada yang default ke lulus.
  • Tanpa pencucian identitas. Penanda tangan yang dilaporkan adalah subjek sertifikat yang terikat secara kriptografis. Entri /Name adalah metadata yang dikendalikan penyerang dan tidak pernah dimunculkan sebagai penanda tangan.
  • Algoritma lemah tidak pernah lulus. Sebuah tanda tangan SHA-1 yang terverifikasi tetap dilaporkan sebagai non-valid; validitas kriptografis di bawah digest yang lemah tidak dicuci menjadi lulus penuh.
  • Trust adalah input, bukan inferensi. Anchor yang Anda sediakan dicocokkan terhadap terminus chain berdasarkan fingerprint DER SHA-256 (RFC 5280 §6.1.1). Konsistensi-diri sebuah chain, atau daftar anchor yang tidak kosong saja, tidak pernah menetapkan trust.
  • Pencabutan bersifat menentukan. Sebuah pernyataan tercabut yang terverifikasi memaksa Invalid terlepas dari setiap pemeriksaan lain; bukti yang tidak tersedia memaksa Indeterminate.
  • Privasi secara default dalam output terserialisasi. toJson() menyamarkan CN penanda tangan, DN root issuer, nama TSA, dan diagnostik masalah chain kecuali Anda memilih keluar, menerapkan minimalisasi data GDPR Article 5(1)(c) pada batas serialisasi.
  • Waktu yang deterministik. Keputusan kesegaran CRL membaca clock PSR-20 yang disuntikkan, bukan wall clock host, sehingga verdict pencabutan dapat direproduksi di bawah pengujian.

NextPDF Enterprise mengimplementasikan perilaku yang diinformasikan oleh ETSI EN 319 102-1 (model status validasi tiga-nilai dan aturan bahwa informasi pencabutan yang tidak tersedia menghasilkan INDETERMINATE), RFC 5652 §5.6 (perhitungan ulang digest sisi verifier), dan RFC 5280 §6.1 (trust anchor sebagai input relying-party untuk validasi jalur). Dukungan bukanlah konformansi, dan konformansi bukanlah sertifikasi. NextPDF tidak memegang sertifikasi dan tidak memberikan sertifikasi. Validator batch bukanlah layanan validasi berkualifikasi, dan statusnya adalah verdict rekayasa yang selaras dengan taksonomi EN 319 102-1 — bukan indikasi TOTAL-PASSED/TOTAL-FAILED/INDETERMINATE dari proses validasi clause 5 yang lengkap. Secara khusus, mode batch tidak melakukan proof-of-existence atau pemrosesan timestamp; sisi verifikasi dokumen tunggal mencakup ranah tersebut.

Validator batch tidak mengonsultasikan kebijakan mode FIPS apa pun, dan mengaktifkan mode FIPS tidak mengubah verdict batch. Penanganan algoritma sisi verifikasinya bersifat tetap dan fail-closed: tanda tangan lemah (SHA-1) tidak pernah dilaporkan Valid, dengan atau tanpa mode FIPS. Kebijakan mode FIPS Enterprise membatasi sisi penandatanganan/pembangkitan, didokumentasikan di FIPS 140 — Deep Reference. Dukungan FIPS 140 adalah pernyataan kapabilitas, bukan klaim validasi atau sertifikasi.

  • validate() melempar \InvalidArgumentException untuk daftar kosong dan \OverflowException di atas 1.000 dokumen. Dokumen yang salah bentuk tidak pernah melempar; mereka menghasilkan hasil error per-dokumen.
  • Valid memerlukan konjungsi: CMS terverifikasi secara kriptografis, chain valid, keanggotaan trust anchor dikonfirmasi, dan RevocationStatus::hasConclusiveGood() bernilai true.
  • Sertifikat yang dikonfirmasi-tercabut bersifat menentukan: verdict-nya adalah Invalid terlepas dari semua bukti lain.
  • Kedua pemeriksaan pencabutan Unknown/Unavailable berarti Indeterminate, bukan Valid (pengetatan 3.1.0, dampak kompatibilitas mundur).
  • Sebuah tanda tangan yang terautentikasi dan chain-valid tanpa trust anchor yang dikonfirmasi adalah Indeterminate — autentik, trust tidak terbukti.
  • signer adalah subjek yang terverifikasi CMS atau string kosong; entri /Name tidak pernah digunakan.
  • timestamp selalu berupa keadaan absent dalam hasil batch.
  • validCount menghitung hanya Valid; semua status lain masuk ke invalidCount, dan status dokumen diagregasi dari penghitung tersebut.
  • toJson() menerapkan CertPiiGuard yang privacy-by-default kecuali sebuah guard diberikan secara eksplisit.
  • Total laporan adalah jumlah eksak atas hasil per-dokumen; durationMs adalah wall time terukur untuk batch tersebut.

Modul Security / Signing milik NextPDF Core adalah sisi produser: ia membuat tanda tangan CMS, menerapkan timestamp RFC 3161, serta memvalidasi chain dan pencabutan untuk material yang disematkannya pada saat penandatanganan. Core tidak menyertakan orkestrator batch sisi verifikasi: tidak ada laporan multi-dokumen, tidak ada taksonomi status agregat, tidak ada verdict pencabutan OCSP/CRL untuk dokumen pihak ketiga, dan tidak ada serialisasi laporan yang terlindungi PII. Pada Core saja, Anda harus mengekstrak dan memverifikasi setiap tanda tangan sendiri serta membangun pelaporan Anda sendiri. Sisi verifikasi dokumen tunggal Enterprise (Verifikasi tanda tangan) dan orkestrator batch ini menyediakan lapisan tersebut.

Halaman ini hanya mendokumentasikan perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefix tiket berada di luar cakupan.