PDF verschlüsseln und Berechtigungen einschränken
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Dieses Recipe zeigt, wie Sie ein Dokument mit dem AES-256-Standard-Sicherheits-Handler verschlüsseln. Dabei setzen Sie ein Benutzerpasswort (zum Öffnen erforderlich) und ein Eigentümerpasswort (voller Zugriff) und schränken Operationen über eine Berechtigungs-Bitmaske ein. Das Recipe benennt bewusst klar, dass diese Berechtigungen auf die Kooperation des Readers angewiesen sind: Verschlüsselung liefert Vertraulichkeit, keine Integrität, und die Berechtigungs-Bits werden nur von kooperierender Software beachtet. Das Recipe orientiert sich an examples/22-protection.php.
Vertrauensgrenze (denken Sie bei jeder Aussage über Berechtigungen daran). PDF-Verschlüsselung schützt die Vertraulichkeit von Inhalten gegenüber Parteien ohne das Passwort (ISO 32000-2 §7.6). Sie schützt nicht die Integrität – sie erkennt oder verhindert keine Änderung. Der Berechtigungseintrag
Pist ein vorzeichenloser 32-Bit-Satz von Flags, den konforme Reader beachten sollen; diese Flags sind keine Zugriffskontrolle. Ein nicht konformes Tool oder ein beliebiges Tool, das mit dem Eigentümerpasswort verwendet wird, kann jede „verweigerte“ Operation ausführen. Beschreiben Sie ein verschlüsseltes PDF nicht als „sicher“, „manipulationssicher“ oder „kopiergeschützt“.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/core:^3Aktivieren Sie die PHP-Erweiterung openssl. Der AES-256-Encryptor nutzt sie für die Chiffre und die Schlüsselableitung.
Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“Der Standard-Sicherheits-Handler wird über die V/R-Codes des Verschlüsselungs-Dictionaries ausgewählt (ISO 32000-2 §7.6). Der Aes256Encryptor von NextPDF implementiert den AESV3-Crypt-Filter auf Sicherheits-Handler-Revision 6 (V=5/R=6): einen zufälligen 256-Bit-Dateiverschlüsselungsschlüssel, eine gesalzene, iterative Hash-Schlüsselableitung (Algorithm 2.B) sowie eine AES-256-CBC-Verschlüsselung pro Objekt mit einem zufälligen Initialisierungsvektor. CBC ist ein Vertraulichkeitsmodus (NIST SP 800-38A). Die zugehörigen IVs müssen unvorhersehbar sein.
Der IV wird pro Objekt und pro Lauf neu erzeugt; deshalb unterscheiden sich die Rohbytes von Lauf zu Lauf. Das Reproduzierbarkeitsprofil ist daher structural. Bevor zwei Läufe verglichen werden, kanonisiert das Harness den Verschlüsselungs-IV, die Objektreihenfolge und das Trailer-/ID. Dieses Profil ist strenger als das einer Recipe ohne Verschlüsselung.
Die Berechtigungs-Bitmaske setzt den P-Eintrag. Bit 3 erlaubt das Drucken, Bit 6 erlaubt annotation/form-fill; der Wert ist die dokumentierte, vorzeichenlose 32-Bit-Größe.
API-Oberfläche
Abschnitt betitelt „API-Oberfläche“NextPDF\Core\Concerns\HasSecurity (in Document eingebunden):
setEncryption(#[SensitiveParameter] string $userPassword, #[SensitiveParameter] string $ownerPassword = '', int $permissions = -1): static— konfiguriert die AES-256-Verschlüsselung über den Standard-Handler.permissions = -1lässt alles zu. WennownerPasswordleer ist, wird das Benutzerpasswort als Eigentümerpasswort wiederverwendet. VoraddPage()aufrufen.getEncryptor(): ?Aes256Encryptor— gibt den konfigurierten Encryptor odernullzurück.useAesGcm(?bool $enabled = true): static— aktiviert bei Bedarf ISO/TS 32003 AES-256-GCM; wirft eine Ausnahme, wenn Host-OpenSSL/libsodium die Chiffre nicht bereitstellt.
Beide Passwortparameter sind mit #[SensitiveParameter] markiert, sodass PHP sie aus Stack-Traces entfernt.
Berechtigungs-Bits (der P-Eintrag, niederwertige Bits 3–6 im üblichen Gebrauch):
| Bit | Wert | Operation |
|---|---|---|
| 3 | 4 | Das Dokument drucken |
| 4 | 8 | Dokumentinhalte ändern |
| 5 | 16 | Text und Grafiken kopieren / extrahieren |
| 6 | 32 | Anmerkungen hinzufügen oder ändern und Formularfelder ausfüllen |
Codebeispiel — Schnellstart
Abschnitt betitelt „Codebeispiel — Schnellstart“<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Confidential Memo');
// Grant printing only (bit 3 = 4). MUST run before addPage().$doc->setEncryption( userPassword: 'open-me', ownerPassword: 'owner-secret', permissions: 4,);
$doc->addPage();$doc->setFont('helvetica', '', 12);$doc->cell(0, 10, 'Encrypted with AES-256; printing allowed only.', newLine: true);
$doc->save(__DIR__ . '/confidential.pdf');echo "Wrote confidential.pdf\n";Codebeispiel — Produktion
Abschnitt betitelt „Codebeispiel — Produktion“Das vollständige Beispiel unten entspricht examples/22-protection.php und schreibt die Ausgabe für das Harness nach NEXTPDF_COOKBOOK_OUTPUT.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$userPassword = 'demo';$ownerPassword = 'admin';
// Grant ONLY printing (bit 3 = 4); deny copy/modify/annotate.$permissions = 4;
$doc = Document::createStandalone();$doc->setTitle('Encrypted Document — Restricted Permissions');$doc->setAuthor('NextPDF Example');
// setEncryption() MUST be called before addPage().$doc->setEncryption( userPassword: $userPassword, ownerPassword: $ownerPassword, permissions: $permissions,);
$doc->addPage();$doc->setFont('helvetica', 'B', 20);$doc->cell(0, 14, 'Encrypted PDF Document', newLine: true);$doc->ln(8);
$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'This document is protected with AES-256 encryption ' . '(standard security handler, revision 6). The user password is required ' . 'to open it; the owner password grants full access. The permission ' . 'bits below are honoured by conforming readers only.');$doc->ln(5);
$permissionTable = [ ['Bit 3 (4)', 'Printing', 'ALLOWED'], ['Bit 4 (8)', 'Content modification', 'DENIED'], ['Bit 5 (16)', 'Text copying / extraction', 'DENIED'], ['Bit 6 (32)', 'Annotations / form fields', 'DENIED'],];$doc->setFont('helvetica', 'B', 10);$doc->cell(30, 7, 'Flag');$doc->cell(60, 7, 'Operation');$doc->cell(0, 7, 'Status', newLine: true);foreach ($permissionTable as [$bit, $operation, $status]) { $doc->setFont('courier', '', 9); $doc->cell(30, 7, $bit); $doc->setFont('helvetica', '', 10); $doc->cell(60, 7, $operation); $doc->setFont('helvetica', 'B', 10); $doc->cell(0, 7, $status, newLine: true);}
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/encrypted.pdf');
echo "Wrote encrypted PDF (AES-256, printing only)\n";Erwartete Ausgabe:
Wrote encrypted PDF (AES-256, printing only)Beim Öffnen der Datei wird nach einem Passwort gefragt. Das Benutzerpasswort öffnet die Datei mit dem eingeschränkten Berechtigungssatz. Das Eigentümerpasswort öffnet sie mit vollem Zugriff.
Randfälle & Stolperfallen
Abschnitt betitelt „Randfälle & Stolperfallen“- Aufrufreihenfolge.
setEncryption()nachaddPage()verschlüsselt früheren Inhalt nicht nachträglich. Konfigurieren Sie die Verschlüsselung immer zuerst; die Engine verschlüsselt jeden Objektrumpf beim Schreiben. - Standardwert des Eigentümerpassworts. Ein leeres Eigentümerpasswort führt dazu, dass die Engine das Benutzerpasswort als Eigentümerpasswort wiederverwendet – dann gibt es faktisch keine privilegierte Rolle. Setzen Sie unterschiedliche Passwörter, wenn sich die beiden Rollen unterscheiden müssen.
- Berechtigungssemantik ist nur ein Richtwert. Die Bits werden nur von konformen Readern beachtet. Sie sind nicht kryptografisch durchgesetzt: Ein nicht konformes Tool oder ein beliebiges Tool, das mit dem Eigentümerpasswort verwendet wird, kann eingeschränkte Operationen ausführen. Behandeln Sie Berechtigungen als Richtlinien-Signal an kooperierende Software, niemals als Zugriffskontrolle, die einer entschlossenen Partei standhält.
- Keine Integritätsgarantie. Verschlüsselung bedeutet Vertraulichkeit, nicht Integrität. Eine Angreiferin oder ein Angreifer ohne das Passwort kann den Inhalt nicht lesen; das Format selbst erkennt jedoch keine Manipulation. Für Integritätsschutz ist ein separater Mechanismus erforderlich (eine digitale Signatur oder ein ISO/TS 32004 Dokument-MAC).
- PDF/A-Konflikt. PDF/A verbietet den Trailer-Schlüssel
Encrypt. Der Aufruf vonsetEncryption()bei einem PDF/A-Dokument wirft – in jeder Reihenfolge – eine Inkompatibilitätsausnahme. - AES-256-GCM-Aktivierung.
useAesGcm()wählt die GCM-Bulk-Verschlüsselung nach ISO/TS 32003, wenn Host-OpenSSL oder libsodium sie bereitstellt; andernfalls wirft es eineInvalidConfigException. Aus demselben Grund ist es mit PDF/A inkompatibel. - Public-Key-Verschlüsselung ist noch nicht verdrahtet.
setPublicKeyEncryption()friert die API-Oberfläche ein, dochsave()wirft, bis die Writer-Verdrahtung gelandet ist (ein bekannter Defekt); verwenden Sie es in Core nicht in der Produktion.
Performance
Abschnitt betitelt „Performance“Die Schlüsselableitung führt den iterierten Hash von Algorithm 2.B einmal pro Dokument aus. Die AES-256-CBC-Verschlüsselung pro Objekt skaliert linear mit der Größe des Objektrumpfs. Für typische Dokumente bleiben die Kosten deutlich innerhalb des Budgets von 1500 ms / 64 MB. Sehr große Dokumente verursachen pro Objekt AES-Durchsatzkosten. GCM mit AES-NI ist auf entsprechend ausgestatteten Hosts schneller.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“- Nur Vertraulichkeit. Noch einmal zur Vertrauensgrenze: Verschlüsselung hält Inhalte von Parteien ohne das Passwort fern; sie beweist nicht, dass die Datei unverändert ist, und die Berechtigungs-Bits sind auf die Kooperation des Readers angewiesen.
- Die Passwortstärke liegt bei Ihnen. Der Handler ist nur so stark wie die Passwörter. Ein schwaches Benutzerpasswort ist offline durch Brute-Force angreifbar, sobald die Datei vorliegt; das Format kann Versuche nicht ratenbegrenzen.
- Das Eigentümerpasswort ist ein Generalschlüssel. Wer das Eigentümerpasswort hat, umgeht jede Einschränkung. Behandeln Sie es wie eine Root-Anmeldeinformation; geben Sie es niemals mit dem Dokument weiter und protokollieren Sie es nicht.
#[SensitiveParameter]ist eine zusätzliche Schutzschicht. Es entfernt die Passwörter aus PHP-Stack-Traces, doch Sie müssen sie trotzdem aus Ihren eigenen Logs, Ausnahmemeldungen und Crash-Berichten heraushalten.
Datenresidenz & PII-Minderungsmaßnahmen
Abschnitt betitelt „Datenresidenz & PII-Minderungsmaßnahmen“Die Bibliothek führt die Verschlüsselung in-process durch. Sie überträgt das Dokument oder die Passwörter an keinen externen Ort. Außer der verschlüsselten Ausgabe, die Sie speichern, schreibt die Engine kein Passwort, keinen Schlüssel und keine Dokument-Bytes auf die Festplatte. Wo die Ausgabedatei liegt und wie die Passwörter verwahrt werden, sind Deployment-Belange, die der Integrator verantwortet. Die Bibliothek gibt keine Residency-Garantie. Wenn das Klartextdokument personenbezogene Daten enthält, sind diese Daten nur so gut geschützt wie das schwächste Passwort und der oben genannte Vorbehalt zum kooperierenden Reader. Verschlüsselung ist kein Ersatz dafür, die in das Dokument aufgenommenen PII zu minimieren.
Sichere Telemetrie & Log-Bereinigung
Abschnitt betitelt „Sichere Telemetrie & Log-Bereinigung“Die Verschlüsselung löst ein EncryptionAppliedEvent aus, das nur den Algorithmusnamen (AES-256) und drei Booleans enthält, die zusammenfassen, ob print/copy/modify erlaubt sind – kein Passwort, kein Schlüssel, kein Salt und kein IV wird jemals an das Event angehängt (src/Event/Security/EncryptionAppliedEvent.php). Der OpenTelemetry-Pfad leitet Span-Attribute durch einen Allowlist-Sanitizer (src/Telemetry/AttributeSanitizer.php), der Passwörter und Dateipfade bedingungslos zurückweist; nur Allowlist-Schlüssel mit skalaren Werten überleben. Fügen Sie in Ihrem eigenen Integrationscode kein Passwort- oder Schlüsselmaterial zu Spans, Logs oder Ausnahmemeldungen hinzu – die #[SensitiveParameter]-Markierungen schützen Stack-Traces, aber nicht Zeichenketten, die Sie selbst erzeugen.
Bedrohungsmodell
Abschnitt betitelt „Bedrohungsmodell“Im Geltungsbereich: eine Angreiferin oder ein Angreifer, die bzw. der die verschlüsselte Datei erlangt, aber nicht die Passwörter hat – der Inhalt ist für diese Person nicht lesbar (vorbehaltlich der Passwortstärke), und die Datei gibt keinen Klartext preis. Außerhalb des Geltungsbereichs: eine Angreiferin oder ein Angreifer, der das Benutzer- oder Eigentümerpasswort hat; ein nicht konformer Reader, der Berechtigungs-Bits ignoriert; Offline-Brute-Force eines schwachen Passworts; Manipulationserkennung (Verschlüsselung liefert Vertraulichkeit, nicht Integrität); Seitenkanäle im Host-OpenSSL-Build; und die Schlüsselverwahrung, die ausschließlich in der Verantwortung des Integrators liegt. Die Dokumentation dieser Bedrohungen behauptet nicht die Abwesenheit von Schwachstellen.
Verhalten im FIPS-Modus
Abschnitt betitelt „Verhalten im FIPS-Modus“Die kryptografischen Primitive werden vom Host-OpenSSL-Build bereitgestellt; daher ist der FIPS-Status eine Eigenschaft des Hosts, keine Einstellung der Bibliothek. CryptoCapabilities::detectFipsMode() gibt ein dreiwertiges FipsModeDetection zurück (src/Security/FipsModeDetection.php): FIPS_ACTIVE, FIPS_ABSENT oder INDETERMINATE. Die PHP-openssl-Erweiterung stellt keine Anbindung an das Provider-Modell von OpenSSL 3 bereit; daher ist die Erkennung nur ein Best-Effort. INDETERMINATE wird als „FIPS nicht nachgewiesen“ behandelt (fail-closed) und lässt sich in operativ nutzbarer Telemetrie unterscheiden. NextPDF beansprucht keine FIPS 140-Validierung; der Betrieb auf einem FIPS-validierten OpenSSL liegt in der Verantwortung des Betreibers, und das Erkennungsergebnis ist nur als Richtwert zu verstehen.
Konformität
Abschnitt betitelt „Konformität“| Aussage | Spezifikation | Abschnitt | reference_id |
|---|---|---|---|
Der V-Code des Verschlüsselungs-Dictionaries wählt den Verschlüsselungsalgorithmus aus. | ISO 32000-2 | §7.6 | |
Die AESV3-Crypt-Filter-Methode wird durch den CFM-Eintrag benannt. | ISO 32000-2 | §7.6 | |
Der P-Eintrag ist eine vorzeichenlose 32-Bit-Zugriffsberechtigungsgröße. | ISO 32000-2 | §7.6 | |
| Berechtigungs-Bit 3 steuert das Drucken. | ISO 32000-2 | §7.6 | |
| Berechtigungs-Bit 6 steuert Anmerkung / Formularausfüllung. | ISO 32000-2 | §7.6 | |
| Verschlüsselung schützt Inhalte vor unbefugtem Zugriff (Vertraulichkeit). | ISO 32000-2 | §7.6 | |
| Die Schlüsselableitung in Revision 6 verwendet gesalzenes iteratives Hashing (Algorithm 2.B). | ISO 32000-2 | §7.6 | |
| CBC ist ein Vertraulichkeitsmodus (kein Integritätsmodus). | NIST SP 800-38A | §6.2 | |
| CBC-Initialisierungsvektoren müssen unvorhersehbar sein. | NIST SP 800-38A | App. C |
NextPDF implementiert die zitierten Abschnitte; es behauptet nicht eine pauschale ISO 32000-2-Konformität, eine FIPS 140-Validierung oder eine rechtliche oder vertragliche Garantie der Vertraulichkeit. „Unterstützung für den Standard-Sicherheits-Handler“ ist keine Zertifizierung der Sicherheit in Ihrem Deployment – diese hängt von der Passwortverwahrung und der Verifizierer-Richtlinie außerhalb der Bibliothek ab.