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

使用PDFBox添加数字签名后Adobe Acrobat显示蓝框及未签名字段问题求助

我正在使用PDFBox库添加签名

我尝试为PDF附加数字签名,并通过Notarius证书颁发机构验证。将证书附加到PDF后用Adobe Acrobat打开,屏幕显示蓝色框而非签名图片;打开签名面板后,显示PDF已认证但包含三个未签名的签名字段(我的PDF原本有三个签名位)。请问出现蓝色框的原因是什么?如何让签名在Adobe Acrobat中可见且状态为已验证?

问题分析

  1. 蓝色框(未激活签名字段):你只创建了签名字段的外观,但没有完成实际签名流程——PDFBox中创建签名字段和完成数字签名是两个独立步骤。当前代码仅添加了空白签名字段,未将证书和签名值嵌入字段,所以Acrobat识别为未签名的空白字段,显示默认蓝色框。
  2. 签名面板显示未签名字段:同理,三个字段都只完成了UI创建,未执行签名加密流程,因此面板标记为未签名。

解决步骤

1. 修正签名字段外观绘制逻辑

当前代码的外观流坐标设置错误,导致签名图片被绘制在可见区域外。修改外观绘制部分:

try (PDPageContentStream cs = new PDPageContentStream(document, appearanceStream)) {
    // 填充字段背景色,使用字段实际尺寸
    cs.setNonStrokingColor(Color.WHITE);
    cs.addRect(0, 0, rectangle.getWidth(), rectangle.getHeight());
    cs.fill();
    if (signImage != null) {
        cs.saveGraphicsState();
        PDImageXObject img = PDImageXObject.createFromFileByExtension(signImage, document);
        // 根据字段尺寸等比例缩放图片,避免超出边界
        float scaleX = rectangle.getWidth() / img.getWidth();
        float scaleY = rectangle.getHeight() / img.getHeight();
        float scale = Math.min(scaleX, scaleY);
        cs.transform(Matrix.getScaleInstance(scale, scale));
        // 居中绘制图片
        float x = (rectangle.getWidth() - img.getWidth() * scale) / 2 / scale;
        float y = (rectangle.getHeight() - img.getHeight() * scale) / 2 / scale;
        cs.drawImage(img, x, y);
        cs.restoreGraphicsState();
    }
}

2. 执行完整数字签名流程

创建签名字段后,需绑定签名对象并完成加密签名:

// 加载密钥库(示例为PKCS12格式)
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("你的密钥库文件.p12"), "密钥库密码".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey privateKey = (PrivateKey) ks.getKey(alias, "密钥密码".toCharArray());
Certificate[] certChain = ks.getCertificateChain(alias);

// 创建签名对象
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("签名者姓名");
signature.setLocation("签名地点");
signature.setReason("签名原因");
signature.setSignDate(Calendar.getInstance());

// 将签名绑定到之前创建的签名字段
signatureField.setValue(signature);

// 执行增量签名(保留原有PDF内容)
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(new FileOutputStream("已签名PDF文件.pdf"));
byte[] content = IOUtils.toByteArray(externalSigning.getContent());
// 生成签名值
SignatureFactory sf = SignatureFactory.getInstance("SHA256withRSA");
Signature sig = sf.getInstance("SHA256withRSA");
sig.initSign(privateKey);
sig.update(content);
byte[] signedBytes = sig.sign();

// 写入签名结果
externalSigning.setSignature(signedBytes);

3. 验证注意事项

  • 确保Notarius的根证书已添加到Adobe Acrobat的受信任证书列表,否则会显示签名未验证。
  • 必须使用分离式签名(SUBFILTER_ADBE_PKCS7_DETACHED),这是Acrobat支持的标准签名格式。
  • 保存PDF时需用增量保存方法,避免破坏原有签名字段结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:50:05