You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PDFBox向已认证签名PDF添加注释致签名失效问题咨询

PDF数字签名与注释添加问题排查

摘要

向带有有效数字签名的特定文档添加注释时,即便采用增量保存且其他同类签名文档无此问题,现有签名仍会失效。唯一能复现该现象的操作是:签名时添加认证(Certified),限制编辑为「仅表单填写、评论和注释」(理论上允许此类操作),但后续以相同方式添加注释仍会导致签名失效。

问题

  1. 对PDF文档进行**认证(Certified)**操作,是否会实际禁止特定注释修改,即便认证明确允许注释?
  2. 我添加注释的方式是否存在特定错误,导致上述问题?
  3. 打开由jSignPDF创建的特定认证级别文档时,Acrobat Reader的签名栏会显示特定印章图标,Acrobat Reader依据哪个属性显示该图标?能否在应用认证级别时避免显示此图标?我有文档存在相同失效行为但无此图标。

场景

现有应用常规向未签名或内部签名的PDF添加印章注释,增量保存后Acrobat Reader会提示「签名后有更改但签名仍有效」。但处理外部签名的PDF时,添加注释会导致签名失效。

我尝试多种方式复现:修改PDF版本(1.4、1.6、1.7)、标记为Tagged、添加LTV信息(OCSP&CRL)、设置认证为「允许表单填写和注释」。使用工具包括LibreOffice 7.5.3.2、qpdf、jSignPDF 2.2.0,仅通过设置认证能复现问题,且确认是增量保存。

补充测试结论

  • LibreOffice导出PDF经jSignPDF非认证签名后,添加注释签名仍有效;
  • Microsoft Word导出PDF经相同签名和注释操作后,签名失效;
  • LibreOffice导出PDF经jSignPDF设置「允许表单填写和注释」认证后,添加注释签名失效,是否为jSignPDF签名方式问题?

测试代码

...
PDPage page = pddoc.getPage(0);
List<PDAnnotation> annotations = page.getAnnotations();

// 优先使用图章注释,因为它不需要定义RC(富文本内容),且Acrobat Reader DC不会尝试修改文档来创建自己的RC表示
PDAnnotationRubberStamp t = new PDAnnotationRubberStamp();

t.setAnnotationName(name); // 可能起重要作用
t.setPrinted(true); // 始终可见
t.setReadOnly(true); // 不与用户交互
t.setContents(text);
t.setHidden(false);
t.setInvisible(false);
t.setLocked(true);

t.setPage(page);
t.setLockedContents(true);

PDFont font = null;
try ( InputStream fs = PDFService.class.getResourceAsStream("/static/fonts/LiberationSans-Bold.ttf")) {
    ret = PDType0Font.load(pddoc, fs, true);
    // PDFBOX会发出警告,但我们忽略此警告
} catch (Exception ex) {
    System.out.println("无法加载字体 : " + ex.getMessage());
}

font.getCOSObject().setNeedToBeUpdated(true);
page.getResources().add(font);
page.getResources().getCOSObject().setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);

subsetFonts.add(font); // 应在添加完页面所有注释后进行字体子集化

PDRectangle rect = new PDRectangle(x, y, 100, 100);
t.setRectangle(rect);

Calendar c = Calendar.getInstance();
t.setCreationDate(c);
t.setModifiedDate(c);

PDAppearanceDictionary ap = new PDAppearanceDictionary();
PDAppearanceStream aps = new PDAppearanceStream(document);
PDAppearanceContentStream apsContent = null;

PDRectangle rect = ann.getRectangle();
rect = new PDRectangle(0, 0, rect.getWidth(), rect.getHeight()); // 必须使用相对坐标,否则注释内容不会显示
aps.setBBox(rect); // 将外观流的边界框设置为注释自身的尺寸

// 多行文本时,从最上方行开始绘制
float initialY = rect.getHeight() - _fontSize;

// 嵌入Unicode字体(必须执行此操作,否则aps.getResources()为null,后续setFont会抛出NPE)
PDResources res = new PDResources();
aps.setResources(res);

try {
    // 直接在XObject的内容流上绘制
    apsContent = new PDAppearanceContentStream(aps);
    apsContent.beginText();
    apsContent.setFont(font, _fontSize); // 若无需支持希腊字符,使用PDType1Font.HELVETICA_BOLD即可
    apsContent.newLineAtOffset(0, initialY);
    apsContent.showText(ann.getContents());
    apsContent.endText();
} 
finally {
    if (apsContent != null) {
        try { apsContent.close(); } catch (Exception ex) { System.out.println(ex.getMessage()); }
    }
}

aps.getResources().getCOSObject().setNeedToBeUpdated(true);
aps.getCOSObject().setNeedToBeUpdated(true);

ap.setNormalAppearance(aps);
ap.getCOSObject().setNeedToBeUpdated(true);
t.setAppearance(ap);

annotations.add(t);
page.setAnnotations(annotations);

t.getCOSObject().setNeedToBeUpdated(true);
page.getResources().getCOSObject().setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
pddoc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
pddoc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

if (font.willBeSubset()) {
    font.subset();
    font.getCOSObject().setNeedToBeUpdated(true); // 对应的页面资源也应标记为需更新——我们已在addAnnotation中处理
}

pddoc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
pddoc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

pddoc.saveIncremental(baos);
...

内容的提问来源于stack exchange,提问作者hello_earth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:38:12