Zum Inhalt springen

Eine vorhandene Signatur prüfen und die Vertrauensgrenze verstehen

Dieses Recipe verwendet den Core-Inspector, um zu erkennen, ob ein PDF eine Signatur enthält, und zieht anschließend die Grenze. Eine Signatur zu erkennen, heißt nicht, sie zu verifizieren. Kryptografische Verifizierung, Validierung des Vertrauenspfads und Sperrprüfung sind Premium-Funktionen oder müssen extern erfolgen.

  • Core installiert: composer require nextpdf/core:^3.
  • Eine PDF-Datei zum Prüfen.
  1. Lesen Sie die PDF-Bytes ein.
  2. Erstellen Sie einen Inspector und rufen Sie inspect() auf.
  3. Lesen Sie InspectResult::$hasSigned aus. true bedeutet, dass die Datei ein Signaturwörterbuch enthält.
  4. Lesen Sie InspectResult::$isEncrypted und die Risiko-Flags für den umgebenden Kontext aus.
  5. Leiten Sie die Datei für die kryptografische Entscheidung an einen Verifizierer weiter. Der Inspector meldet das Vorhandensein, nicht die Gültigkeit.

Das folgende Diagramm zeigt zwei Dinge: die Grenze, die dieses Recipe klarzieht (Vorhandensein ist nicht Gültigkeit), und den vollständigen Satz an Prüfungen, den eine echte Verifizierung weiterhin leisten muss.

false

true

Yes

No

Yes

No / unknown

Incoming PDF

Inspector.inspect — Quick

hasSigned?

No signature present

Signature dictionary PRESENT

NOT yet validity

Recompute byte-range digest

ISO 32000-2 §12.8.1

Validate CMS SignedData

Build & check X.509 path

to a chosen trust anchor

Check revocation OCSP / CRL

Long-term input?

Read DSS validation material

All checks evaluated

Every check passed?

Trustworthy

Not trusted — do not act

Diagram
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\Inspector;
use NextPDF\Inspect\InspectConfig;
$pdfData = file_get_contents(__DIR__ . '/incoming.pdf');
if ($pdfData === false || $pdfData === '') {
fwrite(STDERR, "Cannot read incoming.pdf\n");
exit(1);
}
$inspector = new Inspector();
// InspectConfig::quick() selects InspectDepth::Quick. This is the only
// depth that runs offline: a default Inspector has no Spectrum sidecar,
// and without a sidecar Quick is the sole path that returns a result.
// Standard and Full require the sidecar (see the SIDECAR-001 edge case).
$result = $inspector->inspect(
$pdfData,
InspectConfig::quick(),
);
// hasSigned reports the PRESENCE of a signature dictionary.
// It does NOT mean the signature verifies.
if ($result->hasSigned) {
echo "A signature is present in incoming.pdf\n";
echo "Encrypted: " . ($result->isEncrypted ? 'yes' : 'no') . "\n";
echo "Next step: run a cryptographic verifier before trusting it.\n";
} else {
echo "No signature found in incoming.pdf\n";
}

Für eine signierte Eingabe:

A signature is present in incoming.pdf
Encrypted: no
Next step: run a cryptographic verifier before trusting it.

Für eine nicht signierte Eingabe:

No signature found in incoming.pdf
  • Vorhandensein ist nicht Gültigkeit — die Grenze. InspectResult::$hasSigned meldet, dass in der Datei ein Signaturwörterbuch vorhanden ist. Es prüft weder die CMS-Struktur noch den Byte-Range-Digest, das Signaturzertifikat, die Zertifikatskette oder den Sperrstatus. Eine manipulierte Datei kann weiterhin hasSigned = true melden. Behandeln Sie das Vorhandensein niemals als Nachweis für Integrität oder Urheberschaft.
  • Was eine vollständige Verifizierung erfordert. Eine vollständige Entscheidung berechnet den Byte-Range-Digest neu und vergleicht ihn (ISO 32000-2 §12.8.1), validiert die CMS SignedData, baut den X.509-Pfad zu einem vertrauenswürdigen Anker auf und prüft ihn sowie die Sperrung über OCSP oder CRL. Für die Langzeitvalidierung liegen die Validierungsdaten im DSS (ETSI EN 319 142-2 §6.3.1). Diese Vorgänge werden über die Verträge SignerInterface und LtvManagerInterface abgebildet; die produktiven Implementierungen werden in den Pro- und Enterprise-Editionen ausgeliefert. Der andere unterstützte Weg ist ein externer Validator.
  • Prüftiefe und der Sidecar (SIDECAR-001). Bei einem standardmäßig erzeugten new Inspector() ist kein Spectrum-Sidecar konfiguriert. Ohne Sidecar liefert nur InspectDepth::Quick ein Ergebnis. InspectDepth::Quick nutzt den prozessinternen PHP-Fallback. InspectDepth::Standard und InspectDepth::Full benötigen beide den Sidecar. Ist kein Sidecar verfügbar, werfen sie eine InspectException mit Code INSPECT-SIDECAR-001 („Spectrum sidecar is required for Standard/Full depth inspection“, retryable = true). Im Konstruktor von InspectConfig ist Standardtiefe Standard voreingestellt. Daher ist ein bloßes new InspectConfig() (oder new InspectConfig(depth: InspectDepth::Standard)) nicht offline nutzbar. Dabei wird SIDECAR-001 geworfen, bevor hasSigned überhaupt gelesen wird. Verwenden Sie InspectConfig::quick() für die Offline-Erkennung des Vorhandenseins, wie in diesem Recipe. Keine der Tiefen führt in Core eine kryptografische Signaturverifizierung durch.
  • Leere Eingabe. Ein leerer String wirft eine InspectException mit Code INSPECT-INPUT-001. Sichern Sie den Lesevorgang ab.
  • Mehrere Signaturen. Das Flag für das Vorhandensein zählt keine Signaturen und unterscheidet auch nicht zwischen einer Genehmigungssignatur und einem Dokumentzeitstempel. Verwenden Sie einen dedizierten Verifizierer, wenn die Anzahl oder das Urteil pro Signatur wichtig ist.
AussageSpezifikationAbschnittreference_id
Der Signaturwert wird im Eintrag Contents des Signaturwörterbuchs gespeichert.ISO 32000-2§12.8.1
Die Verifizierung berechnet den Digest über den ByteRange neu und schließt den Signaturwert aus.ISO 32000-2§12.8.1
Validierungsdaten für die Langzeitvalidierung liegen im DSS.ETSI EN 319 142-2§6.3.1

Dieses Recipe erkennt eine Signatur. Es behauptet nicht, dass eine Signatur gültig, vertrauenswürdig oder ungesperrt ist. Diese Entscheidung gehört zu einem kryptografischen Verifizierer.