Je travaille sur une implémentation où notre système génère un fichier PDF qu'un utilisateur peut télécharger. La clé de notre processus et de notre système est que ce fichier PDF ne doit pas être modifiable par l'utilisateur ou par un programme sur l'ordinateur de l'utilisateur (du moins, pas sans mauvaise intention) car le fichier peut être téléchargé sur le système plus tard où nous devons nous assurer que le fichier est dans son état d'origine en comparant sa valeur de hachage.
Nous pensions y être parvenus en désactivant d'abord toutes les autorisations (CanModify, CanAssembleDocument, etc.), puis en chiffrant le document à l'aide du mot de passe du propriétaire. Cela empêchait la modification du fichier par tous les lecteurs auxquels nous avions accès. Il s'avère maintenant que l'un de nos utilisateurs modifie un PDF dès qu'il ouvre le fichier dans Acrobat Reader et "enregistre sous" le document dans un nouveau fichier PDF. Nous ne pouvons pas reproduire ce phénomène avec la même version d'Acrobat Reader (2015.006.30497), mais lui le peut, à chaque fois.
La solution consistant à signer le document PDF n'est pas envisageable pour nous, du moins pas avec une ICP ou une signature visible par les utilisateurs dans leur lecteur. S'il existait une option de signature invisible, ce serait formidable, mais je ne sais pas comment.
Vous trouverez ci-dessous le code que nous utilisons pour verrouiller le PDF. À des fins de test, nous avons désactivé TOUTES les autorisations, mais en vain. Nous utilisons PDFBox 2.0.11.
Quelles sont les options possibles pour mieux verrouiller le fichier en cas de modification ?
public static byte[] SealFile(byte[] pdfFile, String password) throws IOException
{ PDDocument doc =PDDocument.load(pdfFile);
ByteArrayOutputStream bos= new ByteArrayOutputStream();
byte[] returnvalue =null;
int keyLength = 256;
AccessPermission ap = new AccessPermission();
//Disable all
ap.setCanModifyAnnotations(false);
ap.setCanAssembleDocument(false); .
ap.setCanFillInForm(false);
ap.setCanModify(false);
ap.setCanExtractContent(false);
ap.setCanExtractForAccessibility(false);
ap.setCanPrint(false);
//The user password is empty ("") so user can read without password. The admin password is
// set to lock/encrypt the document.
StandardProtectionPolicy spp = new StandardProtectionPolicy(password, "", ap);
spp.setEncryptionKeyLength(keyLength);
spp.setPermissions(ap);
doc.protect(spp);
doc.save(bos);
doc.close();
bos.flush();
return bos.toByteArray();
}
Il en résulte des propriétés Adobe :
Editer (solution) : \==========
Comme suggéré par @mkl, (tous les crédits à cette personne) nous avons pu résoudre le problème avec l'utilisation de l'indicateur appendOnly, qui fait partie de la fonctionnalité AcroForm. Il s'est avéré que l'indicateur signatureExists n'était pas nécessaire pour résoudre notre problème. (et après avoir lu les spécifications, il n'était pas applicable).
Voici la solution que nous avons mise en œuvre :
/*
* This method is used to add the 'appendOnly flag' to the PDF document. This flag is part of
* the AcroForm functionality that instructs a PDF reader that the file is signed and should not be
* modified during the 'saved as' function. For full description see PDF specification PDF 32000-1:2008
* (https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf)
* paragraph 12.7.2 Interactive Form Dictionary
*/
public static void addAcroFormSigFlags(PDDocument pdfDoc) {
PDDocumentCatalog catalog = pdfDoc.getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm();
if (acroForm == null) {
acroForm = new PDAcroForm(pdfDoc);
catalog.setAcroForm(acroForm);
}
// AppendOnly:
// If set, the document contains signatures that may be invalidated if the
// file is saved (wirtten) in a way that alters its previous contents, as
// opposed to an incremental update. Merely updating the file by appending
// new information to the end of the previous version is safe (see h.7,
// "Updating Example"). Conforming readers may use this flag to inform a
// user requesting a full save that signatures will be invalidated and
// require explicit confirmation before continuing with the operation
acroForm.setAppendOnly(true);
// SignatureExists: (Currently not used by us)
// If set, the document contains at least one signature field. This flag
// allows a conforming reader to enable user interface items (such as menu
// items or pushbuttons) related to signature processing without having to
// scan the entire document for the presence of signature fields.
// acroForm.setSignaturesExist(true);
// flag objects that changed (in case a 'saveIncremental' is done hereafter)
catalog.getCOSObject().setNeedToBeUpdated(true);
acroForm.getCOSObject().setNeedToBeUpdated(true);
}