Enterprise edisi
Verifikasi tanda tangan — Referensi Mendalam
Sekilas pandang
Bagian berjudul “Sekilas pandang”Halaman ini adalah referensi mendalam untuk surface AdES verify-side di NextPDF Enterprise. Titik masuknya adalah NextPDF\Enterprise\Security\Validation\AdESValidationEngine. Ia mengimplementasikan alur validasi NextPDF yang dimodelkan menurut ETSI untuk pemeriksaan basic, with-time, long-term, dan archival timestamp: basic validation, validation with time, validation with long-term data, dan archival DocTimeStamp coverage-chain validation. Hasilnya berupa nilai ValidationReport yang membawa case enum MainIndication dan SubIndication dengan nilai string ETSI URN. Surface pendukung yang didokumentasikan di sini: SPI SignatureDataExtractor dan implementasi CmsSignatureDataExtractor-nya, scanner byte-level PdfSignatureDictionaryScanner, surface path-validation NextPDF\Enterprise\Security\Pki, dan BatchSignatureValidator. Untuk panduan tingkat alur kerja, lihat Verifikasi tanda tangan: AdES / PAdES cryptographic verify-side.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini disertakan dalam NextPDF Enterprise (nextpdf/enterprise) dan aktif dengan envelope lisensi tier Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Permukaan API publik
Bagian berjudul “Permukaan API publik”| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
AdESValidationEngine::__construct | 11 parameter opsional: ?PathValidatorInterface $chainValidator, ?SignatureDataExtractor $extractor, ClockInterface $clock, ?LoggerInterface $logger, string $defaultPolicy, NetworkPolicy $networkPolicy, dan lima kolaborator verifier opsional | Semua default bersifat fail-closed: Pki path validator atas clock engine, tanpa extractor, tanpa TSA trust store | Engine baru | Tidak melempar | Tanpa trust store, evaluasi TSA-chain melaporkan untrusted; itu memetakan ke INDETERMINATE, tidak pernah pass |
AdESValidationEngine::validateBasic | string $signedData, string $signature | Basic validation: format, digest, crypto, weak-algorithm, chain, revocation yang di-gate provenance | ValidationReport | Tidak melempar; kegagalan extraction dan path memetakan ke laporan fail-closed | Tanpa extractor, hanya guard check; lihat edge case |
AdESValidationEngine::validateWithTime | string $signedData, string $signature, DateTimeImmutable $claimedTime | Basic validation dulu; jendela sertifikat dan revocation dibandingkan terhadap claimed time | ValidationReport | Tidak melempar | Strict signature-timestamp gate ketika atribut hadir; $claimedTime tetap menjadi time anchor |
AdESValidationEngine::validateWithLongTermData | string $signedData, string $signature, array $dssData (certs/ocsps/crls) | Basic pass wajib; signature-timestamp gate diaktifkan dengan TSA-at-genTime; gate POE, DSS revocation, dan archival | ValidationReport | Tidak melempar | NetworkPolicy::STRICT_OFFLINE dengan data tertanam yang tidak cukup menghasilkan INDETERMINATE / TRY_LATER |
AdESValidationEngine::validateArchivalTimestampChain | string $pdfBytes, array $dssData = [], ?TrustAnchorStoreInterface $anchors = null | Coverage chain DocTimeStamp berbasis bukti atas byte ByteRange yang persis | ValidationReport | Tidak melempar pada byte yang hostile | TOTAL_PASSED hanya untuk chain yang trusted dan mencakup EOF |
MainIndication | — | Enum yang di-back string, tiga case | — | — | Nilai ETSI URN; lihat daftar case di bawah |
SubIndication | — | Enum yang di-back string, lima belas case | — | — | Nilai ETSI URN; lihat daftar case di bawah |
ValidationReport::__construct | MainIndication $mainIndication, ?SubIndication $subIndication, DiagnosticData $diagnosticData, DateTimeImmutable $validationTime, string $validationPolicy = '' | Hasil validasi yang immutable (final readonly) | Report baru | Tidak melempar | isPassed(), isFailed(), isIndeterminate(), toArray() |
DiagnosticData::__construct | array $certificateChain, array $timestamps, array $revocationData, string $validationPolicy, string $signatureFormat, array $warnings (semua di-default) | Kontainer bukti yang immutable; hanya audit trail | Nilai baru | Tidak melempar | toArray() menserialisasi referensi untuk pelaporan |
SignatureDataExtractor::extract | string $signedData, string $signature | SPI: parse CMS dan ekstrak komponen validasi | ExtractedSignatureData | SignatureExtractionException ketika tanda tangan tidak dapat di-parse | Interface; memisahkan parsing ASN.1 dari engine |
CmsSignatureDataExtractor::extract | string $signedData, string $signature | Ekstrak plus verifikasi secara kriptografis sebuah detached PAdES basic signature | ExtractedSignatureData | SignatureExtractionException hanya ketika CMS sama sekali tidak dapat di-parse | Kegagalan crypto atau binding mengembalikan data dengan cryptoValid / hashValid false; ia tidak pernah melempar untuk itu |
PdfSignatureDictionaryScanner::scan | string $pdfBytes | Scan byte-level untuk dictionary /ByteRange + /Contents dengan cross-check anti-spoof yang pas-persis | list<PdfSignatureOccurrence> | Total; tidak pernah melempar; kandidat yang malformed dilewati | Diurutkan berdasarkan akhir coverage, paling awal dulu |
PathValidatorInterface::validate | array $chain, ?DateTimeImmutable $validationTime = null, array $initialPolicies = [] | RFC 5280 §6.1.4 path validation dengan policy processing | PathValidationResult | PathValidationException pada chain yang secara struktural invalid atau batas adversarial yang terlanggar | Chain adalah end-entity dulu, anchor terakhir |
PathValidatorInterface::validateWithAiaChasing | array $chain, ?DateTimeImmutable $validationTime = null | Resolusi AIA atas intermediate yang hilang, lalu validasi | PathValidationResult | PathValidationException | Fetch dibatasi oleh timeout dan batas byte |
CertificateChainValidator | Constructor: engine, PathValidationOptions, clock, logger; static withDefaults() | Implementasi SPI dengan cap adversarial default | PathValidationResult dari kedua metode | PathValidationException | Juga dilempar ketika OpenSSLCertificate tidak dapat diekspor ke PEM |
PathValidationOptions::__construct | Cap (maxDepth, maxPolicyFanout, fetchTimeoutSeconds, fetchSizeCapBytes) plus flag policy, ?TrustAnchorStoreInterface $trustAnchors, bool $requireTrustedAnchor | Depth 32, fanout 64, 5 s per fetch, 10 MiB per fetch; semua flag false | Options baru | Tidak melempar | Factory: defaults(), strict(), withTrustAnchors() |
PathValidationResult::__construct | bool $valid, string $trustAnchorFingerprint, DateTimeImmutable $validatedAt, array $validPolicies, ?RevocationCheckResult $revocation, bool $trustAnchorTrusted, array $fetchedCertificates, array $failureReasons | Hasil yang immutable; trustAnchorTrusted default false (fail-closed) | Nilai baru | Tidak melempar | Keanggotaan trust berbeda dari validitas struktural |
PolicyProcessor | Constructor: PolicyTreeState $state, PathValidationOptions $options; processCertificate(string $certDer, int $depth, bool $selfIssued), finalizeWrapUp(), tree() | RFC 5280 §6.1.4 ekspansi, mapping, dan wrap-up policy-tree | void / list<non-empty-string> / PolicyTree | PathValidationException pada kegagalan policy-processing apa pun (fail-closed) | Wrap-up mengembalikan OID policy yang bertahan, tidak termasuk anyPolicy |
PolicyTree | attach(PolicyTreeNode $node, PathValidationOptions $options), enforceFanout(...), remove(...), plus read query | State valid_policy_tree dengan indeks depth | Bervariasi per metode | PathValidationException ketika jumlah leaf yang aktif melebihi cap fanout | Mengekspos ANY_POLICY_OID (2.5.29.32.0) |
NameConstraintsChecker::processCertificate | string $certDer, bool $applyNameCheck | Mengakumulasi dan menegakkan subtree permitted / excluded per RFC 5280 §6.1.4(g) | void | PathValidationException pada subtree yang dilanggar, bentuk GeneralName yang tidak didukung dalam constraint, atau cap yang terlanggar | Nama yang non-comparable ditangani secara fail-closed |
TrustAnchorStoreInterface::containsFingerprint | string $anchorDerSha256Hex | Keanggotaan berdasarkan hex SHA-256 lowercase atas sertifikat DER anchor | bool | Tidak melempar | Seam trust yang dikonsultasikan oleh path validator |
BatchSignatureValidator::validate | array $inputs (list<DocumentSignatureInput>) | Validasi tanda tangan multi-dokumen dengan caching revocation per-batch | BatchValidationReport | InvalidArgumentException pada list kosong; sebuah resource guard menolak batch di atas 1000 dokumen | Berada di NextPDF\Enterprise\Signature |
final class AdESValidationEnginepublic function validateBasic(string $signedData, string $signature): ValidationReportpublic function validateWithTime( string $signedData, string $signature, DateTimeImmutable $claimedTime,): ValidationReportpublic function validateWithLongTermData( string $signedData, string $signature, array $dssData,): ValidationReportpublic function validateArchivalTimestampChain( string $pdfBytes, array $dssData = [], ?TrustAnchorStoreInterface $anchors = null,): ValidationReportpublic function validate( array $chain, ?DateTimeImmutable $validationTime = null, array $initialPolicies = [],): PathValidationResult;public function validateWithAiaChasing( array $chain, ?DateTimeImmutable $validationTime = null,): PathValidationResult;public static function withDefaults( ?ClockInterface $clock = null, ?AiaChaser $aiaChaser = null, ?LoggerInterface $logger = null,): selfpublic function containsFingerprint(string $anchorDerSha256Hex): bool;public function extract(string $signedData, string $signature): ExtractedSignatureData;public function scan(string $pdfBytes): arraypublic function validate(array $inputs): BatchValidationReportEnum indikasi. Case MainIndication: TOTAL_PASSED, TOTAL_FAILED, INDETERMINATE. Nilai backing mengikuti pola urn:etsi:019102:mainindication:total-passed (lowercase, dengan tanda hubung). Case SubIndication: HASH_FAILURE, SIG_CRYPTO_FAILURE, REVOKED, EXPIRED, NOT_YET_VALID, NO_POE, TRY_LATER, CERTIFICATE_CHAIN_GENERAL_FAILURE, FORMAT_FAILURE, REVOKED_CA_NO_POE, CRYPTO_CONSTRAINTS_FAILURE, POLICY_PROCESSING_FAILURE, REVOCATION_OUT_OF_BOUNDS_NO_POE, NO_SIGNING_CERTIFICATE_FOUND, TIMESTAMP_ORDER_FAILURE. Masing-masing di-back oleh urn:etsi:019102:subindication:<CASE_NAME> dengan nama case yang persis.
Kontrak perilaku
Bagian berjudul “Kontrak perilaku”- Report masuk, report keluar. Keempat titik masuk engine mengembalikan sebuah
ValidationReportuntuk input yang hostile alih-alih melempar. SebuahSignatureExtractionExceptionyang tertangkap dialihkan ke guard path; sebuahPathValidationExceptionyang tertangkap memetakan keTOTAL_FAILED/CERTIFICATE_CHAIN_GENERAL_FAILURE. - Urutan basic validation. Format check dulu; sebuah struktur yang tidak dapat di-parse adalah
TOTAL_FAILED/FORMAT_FAILURE(EN 319 102-1 §5.3.4). Lalu digest (HASH_FAILURE) dan verifikasi kriptografis (SIG_CRYPTO_FAILURE), sesuai dengan hasil building-block EN 319 102-1 §5.2.7.4. Digest dihitung ulang oleh verifier dan dibandingkan dengan signed attributemessageDigest(RFC 5652 §5.6); digest yang dipasok producer tidak pernah dipercaya. - Algoritma lemah terdegradasi. Sebuah tanda tangan yang terverifikasi di bawah SHA-1, atau dengan binding signing-certificate yang lemah, mengembalikan
INDETERMINATE/CRYPTO_CONSTRAINTS_FAILURE, tidak pernahTOTAL_PASSED. Time path menegaskan ulang ini sehingga sebuah tanda tangan yang lemah tidak pernah dilaunder menjadi pass yang time-valid. - Gate provenance revocation. Flag revocation dari extractor dikonsultasikan hanya ketika extractor benar-benar melakukan revocation check (
revocationCheckedtrue). Sebuah default yang tidak dicek bukan “verified not revoked” maupun pemicuREVOKED. Bukti revocation dibangun oleh DSS path. - Propagasi non-pass. Time dan long-term path tidak pernah meng-upgrade hasil basic yang non-pass. Satu pengecualian ada: sebuah basic
INDETERMINATE/REVOKEDdiselesaikan terhadap$claimedTime; revocation pada atau sebelum claimed time adalahTOTAL_FAILED/REVOKED. Ini mencerminkan pola EN 319 102-1 §5.3.4 tentang menyelesaikan sebuah indeterminate terkait revocation dengan bukti waktu. Ketika perbandingan tidak dapat dilakukan, laporan basic yang belum terselesaikan dipropagasikan secara verbatim. - Strict signature-timestamp binding (fail-closed; BC break). Ketika CMS membawa sebuah unsigned attribute
id-aa-timeStampToken, kehadirannya memicu enforcement di time dan long-term path; tidak ada mode warn-only. Kardinalitas harus tepat satu atribut dengan tepat satu nilai (EN 319 122-1 §5.3); bentuk lain apa pun adalahTOTAL_FAILED/FORMAT_FAILURE. Token harus terverifikasi secara kriptografis end to end; sebuah token yang tidak dapat diverifikasi, sebuah konflik parser-differential, atau sebuah imprint mismatch adalahINDETERMINATE/TIMESTAMP_ORDER_FAILURE. Sebuah algoritma imprint yang tidak didukung atau SHA-1 adalahINDETERMINATE/CRYPTO_CONSTRAINTS_FAILURE. Aturan binding-nya adalah RFC 3161 Appendix A:messageImprinttoken harus sama dengan hash dari octet nilaisignatureSignerInfo, dibandingkan dalam constant time. - Gate long-term path. Dalam path yang dianotasi clause 5.4, signature timestamp yang terikat tambahan menerima evaluasi TSA-certificate pada
genTimetoken; sebuah anchor yang untrusted adalahINDETERMINATE/CERTIFICATE_CHAIN_GENERAL_FAILURE, tidak pernah pass.NetworkPolicy::STRICT_OFFLINEdengan material DSS tertanam yang tidak cukup mengembalikanINDETERMINATE/TRY_LATER. Temuan proof-of-existence, DSS revocation, dan archival-chain masing-masing short-circuit keINDETERMINATEdengan sub-indication yang dipetakan. - Gate archival chain. Tidak adanya DocTimeStamp adalah
INDETERMINATE/NO_POE. Sebuah ByteRange yang secara struktural tidak konform adalahTOTAL_FAILED/FORMAT_FAILURE. Setiap token harus terverifikasi, mengikat imprint-nya ke byte yang persis dicakup ByteRange, dan lulus facet mapping TSA-at-genTime (EXPIRED,NOT_YET_VALID,REVOKED_CA_NO_POE,CERTIFICATE_CHAIN_GENERAL_FAILURE, atauTRY_LATERdi bawah strict-offline). Urutan ditegakkan:genTimenon-decreasing, coverage yang berkembang secara ketat, dan token belakangan mengandung lubang/Contentstoken sebelumnya. Token terbaru harus mencakup byte final; byte yang tertinggal adalahTIMESTAMP_ORDER_FAILURE. SebuahgenTimelebih dari 300 detik di depan clock verifier adalahTIMESTAMP_ORDER_FAILURE. - Diagnostik tidak pernah memutuskan. Entri proof-of-existence
DiagnosticData::$timestampshanya audit-trail. Mereka tidak pernah mengubah suatu indikasi, dan akumulator direset di setiap titik masuk. - Batas Pki mendahului crypto. Cap
PathValidationOptions(depth 32, policy fanout 64, 5 s dan 10 MiB per fetch) diperiksa sebelum pekerjaan yang mahal.PathValidationResult::$trustAnchorTrustedberbeda dari$valid;requireTrustedAnchormembuat sebuah terminus yang tidak ditegaskan menjadi invalid.strict()mengaktifkanrequireExplicitPolicy, revocation transport hard-fail, danrequireTrustedAnchor. Validitas path bersifat anchor-relative per RFC 5280 §6.1: sebuah path yang valid dimulai pada sebuah trust anchor yang dipasok sebagai input. - Surface batch.
BatchSignatureValidator::validate()melemparInvalidArgumentExceptionuntuk list kosong dan menolak batch di atas 1000 dokumen melalui sebuah resource guard. PHP menguasai seluruh validasi kriptografis dalam pipeline tersebut.
Edge case & mode kegagalan
Bagian berjudul “Edge case & mode kegagalan”- Engine default tidak punya extractor.
new AdESValidationEngine()hanya melakukan guard check: signature atau signed data yang kosong adalahTOTAL_FAILED; setiap pasangan non-kosong resolve keINDETERMINATE/NO_SIGNING_CERTIFICATE_FOUND, tidak pernahTOTAL_PASSED. InjectNextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractoruntuk memperoleh verifikasi kriptografis. - Default TSA trust check tidak punya store. Setiap TSA chain kemudian melaporkan untrusted, sehingga hasil signature-timestamp archival dan long-term tetap
INDETERMINATE. Pasok anchor viavalidateArchivalTimestampChain(..., $anchors)atau sebuahTsaCertificateAtGenTimeCheckyang terkonfigurasi. $pdfByteskosong.validateArchivalTimestampChain('')mengembalikanTOTAL_FAILED/FORMAT_FAILURE.- Signature timestamp pra-fix tidak dapat pass. Token yang diproduksi oleh versi NextPDF sebelum fix strict-binding meng-imprint input yang berbeda. Mereka gagal pada binding Appendix A secara permanen; tanda tangani ulang dan timestamp ulang untuk memulihkan hasil positif. Ini adalah sebuah BC break yang disengaja dan terdokumentasi.
- DocTimeStamp yang duplikat atau tumpang tindih. Sebuah duplikat pada revisi yang sama, coverage yang sama atau tumpang tindih, atau sebuah token belakangan yang tidak mengandung lubang signature token sebelumnya gagal pada gate ordering.
- Scanner bersifat total dan byte-level.
scan()melewati kandidat yang malformed atau spoofed secara diam-diam; sebuah decoy/ByteRangedi dalam sebuah content stream ditolak. Ia tidak me-resolve indirect object maupun menelusuri cross-reference table. - Coverage, bukan reachability.
validateArchivalTimestampChain()membuktikan coverage byte-range kriptografis hingga end-of-file. Analisis reachability tingkat-objek (misalnya, sebuah document root yang di-re-point di dalam sebuah revisi yang tercakup) dinyatakan di luar cakupan. - Penggunaan Pki langsung melempar. Memanggil implementasi
PathValidatorInterfacesecara langsung memunculkanPathValidationExceptionuntuk chain yang secara struktural invalid, cap yang terlanggar, bentuk constraint yang tidak didukung, dan ekspor PEM yang gagal dari sebuah handleOpenSSLCertificate. Engine menangkap kelas ini; pemanggil Anda sendiri harus menanganinya.
Perilaku mode-FIPS
Bagian berjudul “Perilaku mode-FIPS”Verify-side menerima RSA PKCS#1 v1.5 dengan SHA-2 dan ECDSA pada P-256/P-384/P-521. Token RSASSA-PSS, EdDSA, dan SHA-3 gagal secara fail-closed sebagai tidak didukung; SHA-1 terdegradasi ke CRYPTO_CONSTRAINTS_FAILURE. Di bawah profil crypto-policy Enterprise FIPS 140-3 (didokumentasikan bersama modul security), constraint berlaku pada algoritma mana yang diterima; alur validasi itu sendiri — perhitungan ulang digest, signature check, binding, path validation — tidak berubah. NextPDF tidak memegang sertifikat FIPS 140-3 dan halaman ini tidak mengeklaim apa pun.
Konformitas
Bagian berjudul “Konformitas”| Claim | Standard | Clause |
|---|---|---|
| Basic Signature validation adalah building block yang dapat digunakan ulang untuk validasi time-stamp dan with-time. | ETSI EN 319 102-1 | §5.3.1 |
Kegagalan integritas memetakan ke HASH_FAILURE; sebuah signature check yang gagal memetakan ke SIG_CRYPTO_FAILURE. | ETSI EN 319 102-1 | §5.2.7.4 |
| Format checking berjalan lebih dulu dan sebuah non-pass menghentikan proses. | ETSI EN 319 102-1 | §5.3.4 |
| Sebuah indeterminate terkait revocation dapat diselesaikan dengan bukti waktu. | ETSI EN 319 102-1 | §5.3.4 |
| Sebuah certification path yang valid dimulai pada sebuah trust anchor yang dipasok sebagai input. | RFC 5280 | §6.1 |
Verifier menghitung ulang content digest; ia harus sama dengan signed attribute messageDigest. | RFC 5652 | §5.6 |
messageImprint signature timestamp meng-hash nilai field signature SignerInfo. | RFC 3161 | Appendix A |
Atribut signature-time-stamp membawa tepat satu AttributeValue. | ETSI EN 319 122-1 | §5.3 |
Semua clause diparafrasekan; NextPDF tidak mereproduksi teks normatif. NextPDF tidak membuat klaim konformitas atau sertifikasi AdES / PAdES apa pun. Dukungan atas sebuah standar bukanlah konformitas terhadapnya, dan konformitas bukanlah sertifikasi — NextPDF tidak memegang sertifikasi dan tidak memberikan satu pun. Engine mengimplementasikan prosedur validasi yang dikutip sebagai kapabilitas; ia bukan sebuah layanan validasi yang qualified atau certified, dan sebuah laporan TOTAL_PASSED adalah sebuah pernyataan kriptografis, bukan sebuah penentuan hukum. Nilai enum menggunakan ulang pola identifier ETSI URN untuk interoperabilitas data laporan; penggunaan ulang itu tidak menegaskan endorsement apa pun.
Catatan pengembangan
Bagian berjudul “Catatan pengembangan”- Mapping label-clause. Source paket menganotasi titik masuk sebagai clause EN 319 102-1 5.2, 5.3, dan 5.4. Corpus kepatuhan menempatkan proses Basic Signature validation itu sendiri pada clause 5.3, dengan building block kriptografis pada 5.2.7.4. Halaman ini mengutip nomor clause yang diambil; kontrak perilaku, bukan label, yang otoritatif.
- Tes deterministik. Setiap perbandingan waktu mengalir melalui
ClockInterfacePSR-20 yang di-inject. Inject sebuah frozen clock untuk menguji window check, batas skew genTime 300-detik, dan keputusan freshness CRL. - Komposisi. Semua kolaborator engine di-inject melalui constructor dan opsional, dengan default yang fail-closed. Path validator default adalah
CertificateChainValidator::withDefaults()atas clock engine; options default menjaga policy dan name-constraint processing menjadi no-op untuk input yang konform dan tidak ter-constraint. - Namespace. Surface engine berada di
NextPDF\Enterprise\Security\Validation, surface path-validation diNextPDF\Enterprise\Security\Pki, dan orchestrator batch diNextPDF\Enterprise\Signature. - Higiene report. Report bersifat immutable dan dapat diserialisasi via
toArray(). Konteks diagnostik direset di setiap titik masuk, sehingga sebuah report tidak pernah membawa bukti dari run sebelumnya pada instance engine yang sama.
Lihat juga
Bagian berjudul “Lihat juga”- Verifikasi tanda tangan: AdES / PAdES cryptographic verify-side — halaman kapabilitas: alur kerja, tabel algoritma, catatan upgrade.
- Signature — Deep Reference — sisi producer PAdES B-LT / B-LTA.
- Validation — Deep Reference — pemeriksaan policy struktural tanpa kriptografi.
- Security — Deep Reference — surface security Enterprise gabungan, termasuk profil FIPS.
- Pemetaan klausa PAdES — B-B, B-T, B-LT, B-LTA di seluruh edisi.
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini mendokumentasikan hanya perilaku yang dapat diamati secara eksternal dan public API surface yang didukung. Path namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefiks tiket berada di luar cakupan.