PDFBox 加密/锁定的 PDF 在 'save as' 期间仍由 Adobe Reader 修改
PDFBox encrypted / locked PDF is still modified by Adobe Reader during 'save as'
我正在开发一个实现,我们的系统会生成一个 PDF 文件供用户下载。
我们的流程和系统的关键是这个 PDF 文件不应该被用户或用户计算机上的程序修改(至少,并非没有恶意),因为该文件可以在以后我们需要制作的地方上传到系统通过比较其哈希值来确保文件处于原始状态。
我们认为我们通过首先禁用所有权限(CanModify、CanAssembleDocument 等)然后使用所有者的密码加密文档来完成此操作。这阻止了我们有权访问的所有 reader 对文件的修改。现在事实证明,我们的一位用户在 Acrobat Reader 和 'save as' 中打开文件后立即将 PDF 修改为新的 pdf 文件。我们无法使用相同的 reader 版本 (2015.006.30497) 重现此内容,但他每次都可以。
我们不能选择签署 PDF 文档,至少不能使用 PKI 或用户可以在其 reader 中看到的任何可见签名。如果有某种不可见的签名选项那就太好了,但我不知道怎么做。
在我们用来锁定 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条目。
Bit position —
Name —
Meaning
1 —
SignaturesExist —
If set, the document contains at least one signature field. This flag allows an interactive PDF processor to enable user interface items (such as menu items or push-buttons) related to signature processing without having to scan the entire document for the presence of signature fields.
2 —
AppendOnly —
If set, the document contains signatures that may be invalidated if the file is saved (written) 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"). Interactive PDF processors 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.
(ISO 32000-2, Table 225 — 签名标志)
因此,您应该在 Catalog 的 AcroForm 词典中设置 SigFlags 条目至 3。如果您的 PDF 还没有表单定义,您可能必须先创建 AcroForm 字典
我正在开发一个实现,我们的系统会生成一个 PDF 文件供用户下载。 我们的流程和系统的关键是这个 PDF 文件不应该被用户或用户计算机上的程序修改(至少,并非没有恶意),因为该文件可以在以后我们需要制作的地方上传到系统通过比较其哈希值来确保文件处于原始状态。
我们认为我们通过首先禁用所有权限(CanModify、CanAssembleDocument 等)然后使用所有者的密码加密文档来完成此操作。这阻止了我们有权访问的所有 reader 对文件的修改。现在事实证明,我们的一位用户在 Acrobat Reader 和 'save as' 中打开文件后立即将 PDF 修改为新的 pdf 文件。我们无法使用相同的 reader 版本 (2015.006.30497) 重现此内容,但他每次都可以。
我们不能选择签署 PDF 文档,至少不能使用 PKI 或用户可以在其 reader 中看到的任何可见签名。如果有某种不可见的签名选项那就太好了,但我不知道怎么做。
在我们用来锁定 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条目。
Bit position — Name — Meaning
1 — SignaturesExist — If set, the document contains at least one signature field. This flag allows an interactive PDF processor to enable user interface items (such as menu items or push-buttons) related to signature processing without having to scan the entire document for the presence of signature fields.
2 — AppendOnly — If set, the document contains signatures that may be invalidated if the file is saved (written) 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"). Interactive PDF processors 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.
(ISO 32000-2, Table 225 — 签名标志)
因此,您应该在 Catalog 的 AcroForm 词典中设置 SigFlags 条目至 3。如果您的 PDF 还没有表单定义,您可能必须先创建 AcroForm 字典