问题是 PDFBox 签名不接受Lock字典考虑在内。
根据 ISO 32000-1(以及类似的 ISO 32000-2):
12.8.2.4 现场MDP
The FieldMDP变换方法应用于检测表单字段列表值的更改。表 256 列出了其变换参数字典中的条目。
[...]
因此,签名的预期处理Lock字典包括添加匹配FieldMDP将数据转换为签名字段值。默认情况下,PDFBox 签名不会执行此操作。
您可以在签名时手动执行以下操作:
PDSignatureField signatureField = FIND_YOUR_SIGNATURE_FIELD_TO_SIGN;
PDSignature signature = new PDSignature();
signatureField.setValue(signature);
COSBase lock = signatureField.getCOSObject().getDictionaryObject(COSName.getPDFName("Lock"));
if (lock instanceof COSDictionary)
{
COSDictionary lockDict = (COSDictionary) lock;
COSDictionary transformParams = new COSDictionary(lockDict);
transformParams.setItem(COSName.TYPE, COSName.getPDFName("TransformParams"));
transformParams.setItem(COSName.V, COSName.getPDFName("1.2"));
transformParams.setDirect(true);
COSDictionary sigRef = new COSDictionary();
sigRef.setItem(COSName.TYPE, COSName.getPDFName("SigRef"));
sigRef.setItem(COSName.getPDFName("TransformParams"), transformParams);
sigRef.setItem(COSName.getPDFName("TransformMethod"), COSName.getPDFName("FieldMDP"));
sigRef.setItem(COSName.getPDFName("Data"), document.getDocumentCatalog());
sigRef.setDirect(true);
COSArray referenceArray = new COSArray();
referenceArray.add(sigRef);
signature.getCOSObject().setItem(COSName.getPDFName("Reference"), referenceArray);
}
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("blablabla");
signature.setLocation("blablabla");
signature.setReason("blablabla");
signature.setSignDate(Calendar.getInstance());
document.addSignature(signature [, ...]);
(创建签名 https://github.com/mkl-public/testarea-pdfbox2/blob/master/src/test/java/mkl/testarea/pdfbox2/sign/CreateSignature.java#L328辅助方法signExistingFieldWithLock
)
关于P签名中的条目Lock评论中讨论的字典:此条目已在 ISO 32000 扩展级别 3 的 Adobe 补充中引入。