Eine Dokumenten-Ingest-Pipeline stellte einmal einen kompletten Stapel juristischer Einreichungen als „verschlüsselt“ unter Quarantäne, obwohl jede Datei in Adobe Acrobat ohne Passwortabfrage geöffnet wurde. Die Prüfung hatte den Sicherheitszustand auf einen einzelnen Boolean reduziert. Die Dateien enthielten tatsächlich ein /Encrypt-Wörterbuch — aber ihre Crypt-Filter standen auf Identity, was bedeutet, dass Strings und Streams im Klartext gespeichert waren. Formal verschlüsselt, praktisch offen, und zwei Tage lang blockiert durch ein falsch gelesenes Flag. Dieser Vorfall definiert gut, was ein echtes Verschlüsselungsaudit leisten muss: nicht „ist es verschlüsselt“, sondern welcher Algorithmus, welche Revision, welche Passwörter, welche Berechtigungen und welche Teile der Datei die Verschlüsselung tatsächlich berührt. PDFlibPas, losLabs PDF-Engine für Delphi und C++Builder, legt alle diese Antworten sowohl über eine flache API als auch über eine typisierte Klassenebene offen.
Was das /Encrypt-Wörterbuch tatsächlich festhält
ISO 32000-1 §7.6 definiert Dokumentsicherheit über eine Handvoll Wörterbucheinträge, und PDFlibPas spiegelt sie eins zu eins im TPDFEncryption-Datensatz: die Filterversion V und Revision R, die die Algorithmusfamilie auswählen, Length für die Schlüsselgröße, die Berechtigungsbits in P, die Validierungsstrings für Besitzer- und Benutzerpasswort O und U plus OE/UE für AES-256, ein EncryptMetadata-Flag sowie die Namen der Crypt-Filter, die auf Strings, Streams und eingebettete Dateien angewendet werden.
Der Datensatz ist gerade deshalb der Freund des Auditors, weil er nicht interpretiert. Der Ingest-Vorfall oben wird in Feldern wie StringFilterIdentity und StreamFilterIdentity sichtbar: Wenn sie true sind, wird der entsprechende Datenbereich überhaupt nicht transformiert, ganz gleich, was der verschlüsselte Status des Dokuments behauptet. Ebenso sagt EncryptMetadata = False, dass die XMP-Metadaten für jeden Indexer lesbar bleiben, obwohl der Seiteninhalt es nicht ist — relevant, wenn Routingregeln von Titel- oder Autorenfeldern abhängen.
Eine Zehn-Zeilen-Sicherheitsprüfung mit der flachen API
Für die meisten Pipelines beantworten vier flache Aufrufe die Alltagsfragen. LoadFromFile gibt bei Erfolg 1 zurück; danach arbeiten die Dokumentinspektoren gegen den entschlüsselten Zustand:
var
PDF: TPDFlib;
begin
PDF := TPDFlib.Create;
try
if PDF.LoadFromFile('contract.pdf', UserPassword) <> 1 then
raise Exception.Create('Open failed: wrong password or damaged file');
Writeln('status : ', PDF.EncryptionStatus); // decrypted / encrypted / unknown
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // RC4 vs AES family
Writeln('strength : ', PDF.EncryptionStrength); // key length class
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
CheckPassword ist wichtiger, als es aussieht. PDF unterscheidet ein Benutzerpasswort, das zum Öffnen erforderlich ist, von einem Besitzerpasswort, das volle Rechte gewährt und Berechtigungen übersteuert. Eine Datei, die mit dem Benutzerpasswort geöffnet wurde, verhält sich sehr anders als eine, die mit dem Besitzerpasswort geöffnet wurde — gleiche Bytes, andere Rechte. Die Klassenebene macht die Unterscheidung explizit: TPDFDocument.HasUserPassword und HasOwnerPassword melden, was gesetzt ist, während IsUserPassword und IsOwnerPassword melden, womit die aktuelle Sitzung tatsächlich geöffnet wurde. Ein Audit-Log sollte diese Unterscheidung festhalten, niemals die Passwortwerte selbst.
Die Strength-Leiter: von 40-Bit-RC4 bis AES-256 Revision 6
Die flachen Funktionen Encrypt und EncryptFile nehmen einen Integer Strength mit fünf sinnvollen Werten: 0 für 40-Bit-RC4, 1 für 128-Bit-RC4, 2 für 128-Bit-AES (lesbar ab Acrobat 7), 3 für 256-Bit-AES, wie es mit Acrobat 9 eingeführt wurde, und 4 für 256-Bit-AES, wie es Acrobat X und neuer verlangen.
Werte 3 und 4 verdienen einen genaueren Blick, denn „AES-256“ sind zwei verschiedene Verfahren. Strength 3 bildet auf Security-Handler-Revision 5 ab, einen Übergangsentwurf, der in Acrobat 9 ausgeliefert und nie von ISO übernommen wurde. Strength 4 bildet auf Revision 6 ab, das Verfahren mit gehärteter Schlüsselableitungsfunktion, das ISO 32000-2 standardisiert. Für neue Dokumente gibt es keinen Grund, 3 zu wählen; für Audits zählt der Unterschied, weil eine Compliance-Regel „AES-256 nach ISO 32000-2“ nur durch R6 erfüllt wird. Auf der Leseseite trennt die Klassenebene die beiden als esAES256Bit und esAES256BitAcroX, und die Eigenschaft EncryptionAcroX beantwortet die R5-oder-R6-Frage direkt.
Berechtigungsbits und ihre Schlüssellängen-Klausel
EncodePermissions packt acht Flags in den Integer, den Encrypt und EncryptFile erwarten: Drucken, Kopieren, Ändern und Notizen hinzufügen bilden die Grundmenge, während Felder ausfüllen, Kopieren für Barrierefreiheit, Zusammenstellen und Drucken in voller Qualität die erweiterte Menge bilden. Die Klausel, die auch die eigene Verschlüsselungsdemo der Bibliothek nennt, lautet: Die erweiterten vier werden erst ab 128-Bit-Stärke beachtet — und ebenso das Herabsetzen der Druckqualität durch Setzen des Full-Quality-Print-Flags auf 0. Codieren Sie eine „nur niedrigauflösender Druck“-Policy in ein 40-Bit-Dokument, drucken Viewer schlicht in voller Qualität.
Die tiefere Einschränkung ist, wer diese Bits durchsetzt. Berechtigungen in PDF sind Anweisungen an konforme Reader, keine kryptografischen Beschränkungen: Der Entschlüsselungsschlüssel ist derselbe, ob Kopieren erlaubt ist oder nicht. Ein stark eingeschränktes Berechtigungsset hält ehrliche Viewer ehrlich. Wenn Ihre Pflicht darin besteht, Extraktion zu verhindern statt sie zu entmutigen, braucht das ein Benutzerpasswort und Prozesskontrollen, und der Auditbericht sollte ausdrücklich sagen, unter welchem der beiden Regime eine Datei steht.
Policy setzen und beweisen, dass sie haftet
Verschlüsselung auf bestehende Dateien anzuwenden erfordert kein Laden in den Objektbaum. EncryptFile verarbeitet Eingabe zu Ausgabe in einem Aufruf, und die Audit-Schleife öffnet das Ergebnis erneut, um den Zustand zu prüfen — ein Muster, das fast wortgleich aus der ausgelieferten Demo stammt:
var
PDF: TPDFlib;
R: Integer;
begin
PDF := TPDFlib.Create;
try
R := PDF.EncryptFile('in.pdf', 'out.pdf', 'owner-secret', 'user-secret', 4,
PDF.EncodePermissions(1, 0, 0, 0, // print allowed; copy/change/notes denied
0, 0, 0, 1)); // extended set: full-quality print only
if (R = 1) and (PDF.LoadFromFile('out.pdf', 'user-secret') = 1) then
begin
Writeln('algorithm = ', PDF.EncryptionAlgorithm);
Writeln('strength = ', PDF.EncryptionStrength);
Writeln('owner pw accepted: ', PDF.CheckPassword('owner-secret'));
end;
finally
PDF.Free;
end;
end;
Teams, die auf Dokumentebene arbeiten, erhalten dieselbe Operation mit typisierten Mengen statt Bit-Packing, was im Code-Review besser lesbar ist:
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
In beiden Fällen ist der Read-back-Schritt keine optionale Zeremonie. Er fängt klassische Deployment-Fehler — eine alte Bibliotheksversion, die die angeforderte Stärke still herabstuft, einen nie geschriebenen Ausgabepfad, einen Berechtigungs-Integer in falscher Argumentreihenfolge — in dem Moment ab, in dem sie passieren, nicht am Schreibtisch des Kunden. GetEncryptionFingerprint liefert Ihnen einen kompakten Wert, den Sie für spätere Vergleiche im Jobdatensatz speichern können.
Audit-False-Positives, für die man codieren sollte
Drei Muster führen in Sicherheitsscannern immer wieder zu falschen Schlussfolgerungen. Erstens der Identity-Crypt-Filter-Fall vom Anfang: ein /Encrypt-Wörterbuch ist vorhanden, echter Inhalt bleibt unberührt — prüfen Sie die Identity-Flags pro Filter, bevor Sie Daten als geschützt deklarieren. Zweitens die Metadaten-Aufspaltung: EncryptMetadata kann in beide Richtungen vom Rest der Datei abweichen, also sagt „die Datei ist verschlüsselt“ nichts darüber, ob das XMP-Paket es auch ist. Drittens eingebettete Dateien: PDF erlaubt einen eigenen Crypt-Filter für Dateianhänge, sodass Anhänge der einzige verschlüsselte Teil eines ansonsten offenen Dokuments sein können oder der einzige Klartextteil eines verschlüsselten. Ein Audit-Datensatz, der die drei Filterzuweisungen getrennt erfasst — Strings, Streams, eingebettete Dateien —, ist gegen alle drei Fallen immun; einer, der einen Boolean speichert, liegt regelmäßig falsch.
Fragen, die Auditoren tatsächlich stellen
Kann ich Verschlüsselung aus einer Datei entfernen, wenn ich das Passwort habe? Ja — DecryptFile(InputFileName, OutputFileName, Password) erledigt das ohne vollständiges Laden, und das Decrypt des geladenen Dokuments macht dasselbe im Speicher. Ob Sie es dürfen, ist eine Policy-Frage, die Ihre Ingest-Regeln ausdrücklich beantworten sollten.
Welche Stärke sollten neue Dokumente verwenden? Strength 4, AES-256 Revision 6, außer Sie müssen Viewer älter als Acrobat X unterstützen. Strength 2 (AES-128) bleibt der pragmatische Mindestwert für sehr alte Viewer-Flotten; die RC4-Optionen existieren für Kompatibilitätsaudits, nicht für neue Ausgabe.
Hindern Berechtigungsflags einen entschlossenen Benutzer am Kopieren von Text? Nein. Sie werden von konformen Viewern beachtet, und ISO 32000 beschreibt sie als Zugriffsberechtigungen, die Reader durchsetzen sollen, nicht als Kryptografie. Kombinieren Sie sie mit einem Benutzerpasswort, wenn Vertraulichkeit die eigentliche Anforderung ist.
Weiterführende Lektüre
Verschlüsselungszustand fließt direkt in Signaturentscheidungen ein — eine Workbench, die Dokumente validiert und signiert, braucht dieselbe Read-back-Disziplin, wie der Artikel zur Compliance- und Signatur-Workbench zeigt. Für Batch-Pipelines, die EncryptFile über Tausende großer Dokumente anwenden, zeigt der Direct-Access-Leitfaden für große PDFs, wie der Speicher flach bleibt.
Die vollständige Verschlüsselungs-API-Referenz steht auf der PDFlibPas-Produktseite.