【问题标题】:"Lock" dictionary in signature field is the reason of broken signature after signing签名字段中的“锁定”字典是签名后签名损坏的原因
【发布时间】:2018-04-18 08:03:09
【问题描述】:

在 PDFBox 2.x 中,我将 /Lock 字典放入签名字段:

import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;

public class SigningUtils {
    public static final COSName COS_NAME_LOCK = COSName.getPDFName("Lock");
    public static final COSName COS_NAME_ACTION = COSName.getPDFName("Action");
    public static final COSName COS_NAME_ALL = COSName.getPDFName("All");
    public static final COSName COS_NAME_SIG_FIELD_LOCK = COSName.getPDFName("SigFieldLock");

    public static void setLock(PDSignatureField pdSignatureField, PDAcroForm acroForm) {
        COSDictionary lockDict = new COSDictionary();
        lockDict.setItem(COS_NAME_ACTION, COS_NAME_ALL);
        lockDict.setItem(COSName.TYPE, COS_NAME_SIG_FIELD_LOCK);
        pdSignatureField.getCOSObject().setItem(COS_NAME_LOCK, lockDict);
    }
}

然后我在签名栏上签名:

PDSignature signature = findExistingSignature(document, signatureFieldName); //This is some method to find signature field and create PDSignature dictionary

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, this);

除了当我在 Adob​​e Acrobat 中打开已签名的文档时,它抱怨文档的内容已更改之外,一切看起来都很好。如果我不添加 /Lock 字典,一切都很好。

有人知道哪里出了问题吗?

【问题讨论】:

  • 您是如何保存文件的?
  • @TilmanHausherr 我在添加/Lock字典后调用save,然后加载到一个新的PDDocument,然后在签名后调用saveIncremental
  • @TilmanHausherr 我必须在一个单独的阶段向文档添加签名字段,在另一个步骤中我放置一个签名,所以我必须在第一阶段调用save。如果我在 Adob​​e Reader 中打开第一阶段创建的文档,然后在该程序中签名,则一切正常。
  • @TilmanHausherr 我已经这样做了 :-) 最后我找到了解决方案 - 我必须在添加 /Lock 字典时添加:lockDict.setInt(COSName.getPDFName("P"), 1);
  • 是的,你是对的,我在 pdf 规范中也没有找到这样的键。该解决方案是基于对 Foxit Reader 生成的 pdf 文件结构的观察。我会尝试进一步阅读,也许有更好的解决方案。

标签: java pdf pdfbox


【解决方案1】:

问题在于 PDFBox 签名没有考虑 Lock 字典。

根据 ISO 32000-1(以及类似的 ISO 32000-2):

12.8.2.4 字段MDP

FieldMDP 转换方法应用于检测表单字段列表值的变化。其变换参数字典中的条目列于表 256。

[...]

  • 作者还可以指定在特定收件人签署文档后,对特定表单字段的任何修改都将使该收件人的签名无效。每个指定的接收者都应有一个单独的签名字段,每个都有一个关联的签名字段锁定字典(参见表 233),指定应为该用户锁定的表单字段。

  • 当接收者对该字段进行签名时,应创建签名、签名参考和转换参数字典。转换参数字典中的ActionFields条目应从签名字段锁定字典的相应字段中复制。

因此,签名 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 [, ...]);

(CreateSignature 辅助方法signExistingFieldWithLock)


关于 cmets 中讨论的签名 Lock 字典中的 P 条目:该条目已在 Adob​​e 对 ISO 32000 的补充,扩展级别 3 中引入。 p>

【讨论】:

  • 一个改进的版本,另外使受签名保护的字段只读和锁定可以找到in this answer
猜你喜欢
  • 2021-12-06
  • 2021-06-09
  • 2022-01-01
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-14
  • 2019-01-05
相关资源
最近更新 更多