Un indicateur de permission n'est pas un mécanisme de sécurité. Le bit qui dit "copie interdite" vit dans le même dictionnaire /Encrypt que la cryptographie, ce qui lui donne un air de contrainte qu'il n'a pas, et dès l'instant où vous traitez les deux comme une seule chose, votre audit se met à produire de mauvaises réponses. La seule question qui vaille au sujet d'un PDF n'est pas "est-il chiffré". Elle est plus précise et plus difficile : quel algorithme, quelle révision du gestionnaire de sécurité, laquelle des deux passphrases a été définie, quels bits de permission sont revendiqués, et quelles parties du fichier le chiffrement touche réellement. Un fichier peut être formellement chiffré et pratiquement ouvert. Il peut refuser d'être lu tout en laissant ses métadonnées en clair. Il peut verrouiller l'impression dans un indicateur que n'importe quelle visionneuse est libre d'ignorer. Auditer un PDF, c'est résoudre tout cela séparément, et PDF Library for Delphi, le moteur PDF de losLab pour Delphi et C++Builder, expose chacun de ces points à travers une API plate à handles entiers et une couche de classes typée
Ce que le dictionnaire /Encrypt consigne réellement
L'ISO 32000-1 §7.6 définit la sécurité du document par une poignée d'entrées de dictionnaire, et PDF Library for Delphi les reflète une à une dans l'enregistrement TPDFEncryption. La version de filtre V et la révision R sélectionnent la famille d'algorithmes. Length porte la taille de clé. Les bits de permission siègent dans P, les chaînes de validation des mots de passe propriétaire et utilisateur dans O et U (avec OE et UE ajoutés pour AES-256), un indicateur EncryptMetadata les accompagne, et trois champs de plus nomment les filtres de chiffrement appliqués respectivement aux chaînes, aux flux et aux fichiers incorporés
La valeur de cet enregistrement tient à ce qu'il n'interprète rien à votre place. Il rend le dictionnaire brut et vous laisse tirer les conclusions, ce qui est exactement ce dont un audit a besoin. Le cas du texte en clair à l'intérieur du chiffré apparaît dans StringFilterIdentity et StreamFilterIdentity : quand l'un des deux vaut vrai, les données correspondantes traversent le filtre Identity sans être touchées, quoi que rapporte l'état chiffré du document. Un scanner qui s'arrête à "un dictionnaire /Encrypt est présent" déclarera protégé un fichier dont les chaînes et les flux sont posés en clair. La même nuance gouverne les métadonnées. Quand EncryptMetadata vaut faux, le paquet XMP reste lisible par n'importe quel indexeur alors que le contenu des pages ne l'est pas, ce qu'il est bon de savoir dès que vos règles de routage s'appuient sur un champ titre ou auteur
Une courte sonde de sécurité avec l'API plate
Pour la plupart des pipelines, quatre appels plats répondent aux questions du quotidien. LoadFromFile renvoie 1 en cas de succès, et une fois le document ouvert, les inspecteurs de chiffrement rapportent son état déchiffré :
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); // déchiffré / chiffré / inconnu
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // famille RC4 ou AES
Writeln('strength : ', PDF.EncryptionStrength); // classe de longueur de clé
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
CheckPassword compte davantage que ne le laisse croire sa signature d'une ligne. Le PDF définit deux mots de passe aux pouvoirs inégaux. Le mot de passe utilisateur est requis pour ouvrir le fichier tout court. Le mot de passe propriétaire accorde tous les droits et prime sur chaque bit de permission. Les octets sur le disque sont identiques dans les deux cas, mais une session ouverte sous le mot de passe propriétaire peut faire des choses que la session sous mot de passe utilisateur ne peut pas ; un audit qui ne consigne pas quelle information a été présentée ne consigne que la moitié de la vérité. La couche de classes rend la distinction interrogeable. TPDFDocument.HasUserPassword et HasOwnerPassword rapportent ce que le fichier exige, tandis que IsUserPassword et IsOwnerPassword rapportent quel mot de passe a réellement ouvert la session en cours. Journalisez ce fait. Ne journalisez jamais les valeurs des mots de passe eux-mêmes
L'échelle Strength, où "AES-256" désigne deux choses
Les fonctions plates Encrypt et EncryptFile prennent un Strength entier avec cinq valeurs utiles : 0 pour RC4 40 bits, 1 pour RC4 128 bits, 2 pour AES 128 bits lisible depuis Acrobat 7, 3 pour AES 256 bits tel qu'introduit avec Acrobat 9, et 4 pour AES 256 bits tel que l'exigent Acrobat X et ses successeurs
Le point intéressant est que 3 et 4 portent tous deux l'étiquette AES-256 sans être le même schéma. Le Strength 3 correspond à la révision 5 du gestionnaire de sécurité, une conception intermédiaire livrée par Acrobat 9 que l'ISO n'a jamais adoptée. Le Strength 4 correspond à la révision 6, dont la fonction de dérivation de clé a été durcie et normalisée dans l'ISO 32000-2. Pour un document que vous créez aujourd'hui, il n'y a aucune raison de préférer 3 à 4. Pour un audit, l'écart est décisif : une politique qui énonce "AES-256 selon ISO 32000-2" n'est satisfaite que par R6, et un fichier R5 qui se dit AES-256 échoue à cette politique tout en passant un contrôle de force naïf. La couche de classes tient les deux séparés par le nom, esAES256Bit pour R5 face à esAES256BitAcroX pour R6, et la propriété EncryptionAcroX répond à la question de la révision par un simple booléen
Les bits de permission et leurs clauses en petits caractères sur la longueur de clé
EncodePermissions tasse huit indicateurs dans l'entier qu'attendent Encrypt et EncryptFile. Impression, copie, modification et ajout de notes forment le jeu de base ; remplissage de champs, copie pour accessibilité, assemblage et impression pleine qualité forment le jeu étendu. Les petits caractères, que la démo de chiffrement de la bibliothèque énonce sans détour, sont que les quatre indicateurs étendus ne prennent effet qu'à partir de 128 bits. L'indicateur d'impression pleine qualité tombe sous la même règle : effacez-le pour forcer une impression basse résolution et un document 40 bits vous ignorera, car cette dégradation exige elle aussi un chiffrement de 128 bits ou plus. Encodez une politique "impression basse résolution seulement" dans un fichier 40 bits et toutes les visionneuses imprimeront quand même en pleine qualité
La question de fond est de savoir qui applique ces bits, et la réponse est personne à qui vous puissiez vous fier. Les permissions sont des instructions aux lecteurs conformes, pas des restrictions cryptographiques. La clé de déchiffrement est identique que la copie soit autorisée ou refusée, si bien qu'un jeu de permissions verrouillé ne fait que garder honnêtes les visionneuses honnêtes. Un lecteur qui choisit d'ignorer les bits ne rencontre aucun obstacle cryptographique. Si l'obligation est d'empêcher l'extraction plutôt que de la décourager, le fichier a besoin d'un mot de passe utilisateur et le flux de travail a besoin de contrôles au niveau du processus autour de lui ; un rapport d'audit devrait nommer lequel des deux régimes s'applique réellement à chaque fichier au lieu de prendre un indicateur de permission pour une serrure
Définir une politique et prouver qu'elle a pris
Appliquer un chiffrement à des fichiers existants ne demande pas de les charger dans l'arbre d'objets. EncryptFile traite l'entrée vers la sortie en un seul appel, et la boucle d'audit rouvre le résultat pour confirmer ce qui a atterri sur le disque. La démo de chiffrement livrée suit la même forme écrire-puis-relire :
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, // impression permise ; copie/modif/notes refusées
0, 0, 0, 1)); // jeu étendu : impression pleine qualité seulement
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;
Les équipes qui travaillent au niveau du document obtiennent la même opération avec des ensembles typés à la place du tassage de bits, ce qui survit à une revue de code en plissant beaucoup moins les yeux :
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
Dans un cas comme dans l'autre, l'étape de relecture n'est pas une cérémonie facultative. Elle attrape les erreurs de déploiement qui remontent autrement des mois plus tard sur la machine d'un client : une ancienne compilation de la bibliothèque qui rétrograde en silence la force demandée, un chemin de sortie jamais écrit parce que le répertoire était en lecture seule, un entier de permissions dont les arguments sont partis dans le mauvais ordre. Les trois passent un test de fumée local et échouent sur le terrain, et rouvrir la sortie transforme chacun d'eux en une exception que vous voyez pendant l'exécution qui a créé le fichier. GetEncryptionFingerprint renvoie une valeur compacte que vous pouvez stocker avec la fiche du travail, si bien qu'une comparaison ultérieure peut dire si deux sorties partagent la même configuration de chiffrement sans rouvrir ni l'une ni l'autre
Les faux positifs d'audit qu'il vaut la peine de coder
Quelques motifs poussent immanquablement les scanners de sécurité vers la mauvaise conclusion, et chacun vient de l'écrasement d'une question à plusieurs volets en une réponse par oui ou non. Le filtre de chiffrement Identity en est l'exemple le plus net. Un dictionnaire /Encrypt est présent, le fichier se déclare chiffré, et pourtant les chaînes et les flux passent par le filtre Identity sans changement, donc le contenu réel est en clair. Lire StringFilterIdentity et StreamFilterIdentity avant de déclarer quoi que ce soit protégé est le correctif
La séparation des métadonnées est plus subtile. EncryptMetadata peut diverger du reste du document dans les deux sens, laissant un fichier chiffré doté d'un paquet XMP lisible ou, plus rarement, l'inverse. "Le fichier est chiffré" ne dit rien de ses métadonnées, ce qui compte dès qu'un indexeur ou une règle de routage va chercher le titre. Les fichiers incorporés ajoutent un troisième axe : le PDF autorise un filtre de chiffrement dédié rien que pour les pièces jointes, si bien que les pièces jointes peuvent être la seule partie chiffrée d'un document par ailleurs ouvert, ou la seule partie en clair d'un document chiffré. Capturez les trois affectations de filtre comme des champs distincts pour les chaînes, les flux et les fichiers incorporés, et aucun de ces pièges ne peut vous attraper. Stockez un unique booléen et le mauvais verdict n'est qu'une question de temps
Retirer le chiffrement, et le choisir pour de nouveaux fichiers
Un audit se termine souvent par la décision de retirer la protection, et la mécanique n'est pas l'obstacle. DecryptFile(InputFileName, OutputFileName, Password) écrit une copie déchiffrée sans chargement complet, et le Decrypt du document chargé fait la même chose en mémoire une fois le fichier déjà ouvert. Les deux exigent un mot de passe valide ; ni l'un ni l'autre ne contourne la cryptographie. La vraie barrière relève de la politique et non du code, alors faites en sorte que vos règles d'admission énoncent clairement quand le retrait est permis et consignez la classe de mot de passe qui l'a autorisé, car l'étape technique elle-même ne laisse aucune trace
Le choix pour une nouvelle sortie est plus étroit que ne le suggèrent les cinq valeurs de Strength. Utilisez le Strength 4, AES-256 révision 6, sauf si vous devez ouvrir les fichiers dans des visionneuses plus anciennes qu'Acrobat X. Le Strength 2, AES-128, est le plancher pragmatique pour un parc de visionneuses vieillissant qui ne peut pas être mis à jour. Les options RC4 en 0 et 1 sont là pour vous permettre de lire et d'auditer des archives historiques, pas pour produire du neuf avec elles ; y recourir dans une conception de 2026 est le signe qu'une exigence en amont est périmée
L'état de chiffrement alimente directement les décisions de signature, puisqu'un atelier qui valide et signe des documents a besoin de la même discipline de relecture sur laquelle repose cet audit. Ce terrain est couvert dans l'article sur l'atelier de conformité et de signature. Quand un lot applique EncryptFile à des milliers de documents volumineux, le guide de l'accès direct aux gros PDF montre comment garder la mémoire à plat pendant l'exécution. La référence complète de l'API de chiffrement se trouve sur la page produit de PDF Library for Delphi