我正在一个实现中,我们的系统生成一个PDF文件供用户下载。我们的流程和系统的关键在于,该PDF文件不应由用户或用户计算机上的程序修改(至少,并非没有恶意),因为该文件可以稍后上传到系统中,通过比较其哈希值,确保文件处于其原始状态。
我们认为我们是通过首先禁用所有权限(CanModify,CanAssembleDocument等),然后使用所有者的密码加密文档来实现的。这阻止了我们有权访问的所有读者对文件的修改。现在事实证明,我们的一位用户在Acrobat Reader中打开文件并将其“另存为”到新的pdf文件后立即对其进行了修改。我们无法使用相同的阅读器版本(2015.006.30497)复制此内容,但他每次都可以。
对我们而言,签名PDF文档不是一种选择,至少不能使用PKI或用户在阅读器中可以看到的任何可见签名。如果有某种不可见的签名选项,那会很好,但我不知道如何。
在用于锁定PDF的代码下方。出于测试目的,我们禁用了所有权限,但无济于事。我们正在使用PDFBox 2.0.11。
有什么建议可以更好地锁定文件以进行修改吗?
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();
}
这将产生Adobe属性:
编辑(解决方案): ==========
正如@mkl所建议的(此人的全部功劳),我们能够通过使用appendOnly标志来解决该问题,该标志是AcroForm功能的一部分。事实证明,解决我们的问题不需要signatureExists标志。(并且在阅读了规格之后,不适用)
以下是我们实施的解决方案:
/*
* 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);
}
即使实际上不签署PDF文档,也可以尝试设置声称存在签名的AcroForm标志。
这应防止对这些标志敏感的程序(如Adobe Reader)将更改应用于PDF,或者至少应将其更改作为增量更新应用,可以通过将文件截短为原始大小来撤消这些更改。
有问题的标志条目是AcroForm词典中的SigFlags条目。
位位置—名称—含义
1 — SignaturesExist(签名存在) —如果设置,则文档至少包含一个签名字段。该标志允许交互式PDF处理器启用与签名处理相关的用户界面项(例如菜单项或按钮),而不必扫描整个文档是否存在签名域。
2 —仅附加—如果设置,则文档包含签名,如果以更改其先前内容(而不是增量更新)的方式保存(写入)文件,则该签名可能无效。通过在新版本的末尾附加新信息来仅更新文件是安全的(请参阅H.7,“更新示例”)。交互式PDF处理器可以使用此标志来通知请求完全保存的用户签名将无效,并需要在继续操作之前进行明确确认。
(ISO 32000-2,表225-签名标志)
因此,你应该设置SigFlags在入门AcroForm字典中的目录,以3。如果您的PDF尚无表单定义,则可能必须先创建AcroForm字典。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句