Lewati ke konten

Memeriksa tanda tangan yang ada dan memahami batas kepercayaan

Gunakan inspector Core untuk mendeteksi apakah sebuah PDF memuat kamus tanda tangan. Inspector berjalan secara offline dan tidak menggunakan sidecar Spectrum. Resep ini juga memperjelas batas kepercayaan: mendeteksi tanda tangan tidak sama dengan memverifikasinya. Verifikasi kriptografis, validasi jalur kepercayaan, dan pemeriksaan pencabutan tersedia di Premium atau melalui jalur eksternal.

Terminal window
composer require nextpdf/core:^3

Tanda tangan PDF direpresentasikan sebagai bidang tanda tangan yang nilainya berupa kamus tanda tangan (ISO 32000-2 §12.7.4). Entri Contents pada kamus tersebut menampung Cryptographic Message Syntax (CMS) SignedData yang dienkode DER (ISO 32000-2 §12.8.1). Fallback Quick pada Inspector mendeteksi keberadaan struktur tersebut dengan memindai penanda tanda tangan. Fallback ini tidak mengurai CMS, menghitung ulang digest rentang byte (yang mengecualikan nilai tanda tangan — ISO 32000-2 §12.8.1), memvalidasi rantai sertifikat, maupun memeriksa pencabutan.

Panggil new Inspector(), lalu ->inspect(string $pdfData, InspectConfig $config). Gunakan InspectConfig::quick() sebagai fallback PHP offline. InspectDepth::Standard/Full memerlukan sidecar Spectrum dan gagal secara tertutup (INSPECT-SIDECAR-001) ketika sidecar tidak tersedia. Hasilnya berupa objek nilai InspectResult. Untuk alur kerja ini, gunakan $hasSigned untuk menunjukkan keberadaan tanda tangan, bersama $isEncrypted dan $pdfVersion.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\InspectConfig;
use NextPDF\Inspect\Inspector;
$pdfData = file_get_contents(__DIR__ . '/incoming.pdf');
if ($pdfData === false || $pdfData === '') {
fwrite(STDERR, "Cannot read incoming.pdf\n");
exit(1);
}
$result = (new Inspector())->inspect($pdfData, InspectConfig::quick());
// hasSigned reports the PRESENCE of a signature dictionary.
// It does NOT mean the signature verifies.
echo $result->hasSigned
? "A signature is present — NOT verified.\n"
: "No signature found.\n";

Program mandiri ini berjalan dalam harness cookbook. Program ini mencerminkan examples/37-inspect-existing-signature.php. Program ini memeriksa sampel korpus yang diketahui sudah bertanda tangan dan dokumen tanpa tanda tangan yang baru dibuat, sehingga Anda dapat mengamati kedua cabang flag keberadaan. Setelah itu program merutekan berdasarkan keputusan tersebut. Keberadaan adalah masukan untuk perutean, bukan keputusan kepercayaan. Berkas tersebut diserahkan ke verifier kriptografis (Pro atau eksternal). Berkas tidak dianggap tepercaya di sini.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Inspect\InspectConfig;
use NextPDF\Inspect\Inspector;
$inspector = new Inspector();
// --- A known-signed input ---
// The repository corpus carries synthetic PAdES samples. In your
// application this is simply the incoming PDF you received.
$signedPath = __DIR__ . '/tests/Corpus/pades/pades-b-b-bytepattern-synthetic.pdf';
if (is_file($signedPath)) {
$signed = (string) file_get_contents($signedPath);
$r = $inspector->inspect($signed, InspectConfig::quick());
echo "Signed sample:\n";
echo ' Signature present : ' . ($r->hasSigned ? 'yes' : 'no') . "\n";
echo ' Encrypted : ' . ($r->isEncrypted ? 'yes' : 'no') . "\n";
echo ' PDF version : ' . ($r->pdfVersion ?? 'unknown') . "\n";
echo " Verdict : presence detected — NOT verified.\n";
if ($r->hasSigned) {
// Presence detected. This is routing input, not a trust verdict.
// Hand the file to a cryptographic verifier (Pro or external)
// before relying on it. (Pseudo-queue shown; wire your own.)
// $verifierQueue->enqueue($signed);
echo " Next step : run a cryptographic verifier before trusting it.\n";
}
} else {
echo "Signed corpus sample absent; skipping the signed branch.\n";
}
// --- A known-unsigned input ---
$unsigned = Document::createStandalone();
$unsigned->setTitle('Unsigned sample');
$unsigned->addPage();
$unsigned->setFont('helvetica', '', 12);
$unsigned->cell(0, 10, 'This document carries no signature.', newLine: true);
$unsignedBytes = $unsigned->getPdfData();
$ru = $inspector->inspect($unsignedBytes, InspectConfig::quick());
echo "Unsigned sample:\n";
echo ' Signature present : ' . ($ru->hasSigned ? 'yes' : 'no') . "\n";
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the
// semantic profile; emit the unsigned document to the side-channel.
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
file_put_contents($out !== false && $out !== '' ? $out : __DIR__ . '/inspected.pdf', $unsignedBytes);

STDOUT yang diharapkan (cabang bertanda tangan akan dilewati jika sampel korpus tidak tersedia):

Signed sample:
Signature present : yes
Encrypted : no
PDF version : <version>
Verdict : presence detected — NOT verified.
Next step : run a cryptographic verifier before trusting it.
Unsigned sample:
Signature present : no
  • Keberadaan bukanlah keabsahan. $hasSigned melaporkan bahwa kamus tanda tangan ada. Flag ini tidak memeriksa struktur CMS, digest rentang byte, sertifikat penanda tangan, rantai, maupun pencabutan. Berkas yang telah dirusak masih dapat melaporkan hasSigned = true. Jangan pernah memperlakukan keberadaan sebagai bukti integritas atau kepengarangan.
  • Apa yang dibutuhkan verifikasi penuh. Keputusan verifikasi yang lengkap menghitung ulang digest rentang byte (ISO 32000-2 §12.8.1), memvalidasi CMS SignedData, membangun dan memeriksa jalur X.509 menuju anchor tepercaya, serta memeriksa pencabutan melalui Online Certificate Status Protocol (OCSP) atau certificate revocation list (CRL). Stempel waktu tanda tangan, ketika ada, juga diverifikasi terhadap imprint-nya sendiri atas oktet nilai tanda tangan (ETSI EN 319 122-1 §5.3). Operasi ini berjalan di balik kontrak penandatanganan. Implementasi produksi disertakan dalam Pro dan Enterprise. Validator eksternal juga merupakan jalur yang didukung.
  • Kedalaman pemeriksaan. InspectConfig::quick() adalah satu-satunya kedalaman yang berjalan tanpa sidecar Spectrum. Standard/Full melempar INSPECT-SIDECAR-001 saat sidecar tidak tersedia.
  • Masukan kosong. String kosong memicu exception inspect dengan pesan “PDF data must not be empty”. Lindungi proses pembacaan.
  • Beberapa tanda tangan / stempel waktu. Flag keberadaan tidak menghitung tanda tangan atau membedakan tanda tangan persetujuan dari stempel waktu dokumen (yang juga dibawa dalam unsignedAttrs menurut RFC 5652 §5.3). Gunakan verifier khusus ketika jumlah atau keputusan per tanda tangan penting.

Fallback Quick melakukan pemindaian terbatas terhadap byte dokumen. Fallback ini tidak mengurai seluruh graf objek. Gunakan fallback ini untuk triase cepat berkas masuk sebelum Anda mengarahkannya ke verifier yang lebih berat.

Inspector adalah alat triase, bukan batas kepercayaan. hasSigned yang positif tidak boleh digunakan sendirian untuk menentukan keputusan kepercayaan.

Pemeriksaan berjalan sepenuhnya dalam proses. Tidak ada byte dokumen yang meninggalkan host. Fallback Quick hanya membaca penanda struktural, bukan teks dokumen, sehingga tidak mengekstrak atau mengirimkan informasi yang dapat mengidentifikasi pribadi (PII).

Inspector menerima logger PSR-3 opsional. Logger ini mencatat jalur yang dipilih (“Spectrum unavailable, using PHP fallback”), bukan isi dokumen. Jangan mencatat byte PDF yang diperiksa atau InspectResult secara verbatim jika dokumen sensitif.

Yang dipertimbangkan: sebuah berkas yang telah dirusak yang menampilkan kamus tanda tangan yang sah secara sintaksis (inspector melaporkan keberadaan; secara eksplisit tidak menyatakan integritas), dan sebuah berkas tanpa tanda tangan (dilaporkan tidak ada dengan benar). Yang tidak dinyatakan: bahwa tanda tangan apa pun yang terdeteksi adalah sah secara kriptografis, tepercaya, atau belum dicabut — semua itu adalah tugas verifier.

Fallback Quick tidak melakukan kriptografi apa pun, sehingga mode Federal Information Processing Standards (FIPS) tidak relevan dengan resep ini. Verifikasi kriptografis (Premium/eksternal) adalah tempat rantai penyedia FIPS menjadi penting.

PernyataanSpesifikasiKlausareference_id
Nilai bidang tanda tangan adalah kamus tanda tangan.ISO 32000-2§12.7.4
Contents menampung DER CMS SignedData; Contents stempel waktu dokumen menampung TimeStampToken.ISO 32000-2§12.8.1
Verifikasi menghitung ulang digest atas rentang byte dengan mengecualikan nilai tanda tangan.ISO 32000-2§12.8.1
Imprint stempel waktu tanda tangan dibuat atas oktet nilai tanda tangan SignerInfo.ETSI EN 319 122-1§5.3
Sebuah stempel waktu dibawa dalam SignerInfo unsignedAttrs.RFC 5652§5.3

Resep ini mendeteksi tanda tangan. Resep ini tidak menyatakan bahwa tanda tangan apa pun sah, tepercaya, atau belum dicabut. Keputusan tersebut dibuat oleh verifier kriptografis.

Verifikasi CMS kriptografis, validasi jalur X.509, dan pemeriksaan pencabutan OCSP/CRL tersedia di balik kontrak penandatanganan dalam edisi Pro dan Enterprise. Inspector Core hanya mencakup deteksi keberadaan.