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

Java使用PdfBox实现PDF外部签名提示签名格式或信息错误如何解决

问题排查及解决方案

核心错误点

  • 重复调用saveIncrementalForExternalSigning:该方法调用会修改PDDocument内部的PDF结构,第一次调用用于获取待签名内容后,不能再次调用该方法嵌入签名,两次生成的待签数字节不一致会直接导致签名校验失败。
  • 多余调用doc.save():saveIncrementalForExternalSigning已经完成了签名的增量写入操作,后续调用普通save方法会覆盖PDF原有增量结构,直接破坏签名完整性。
  • 签名值格式不匹配:你使用的SUBFILTER_ADBE_PKCS7_DETACHED子过滤器要求传入的是包含证书链、签名值、可选时间戳的完整PKCS7容器,而你提供的Base64签名值解码后仅为512字节,大概率是单纯的RSA签名结果,不符合PDF签名的格式要求。

修复后正确流程

// 1. 初始化签名对象
PDDocument doc = PDDocument.load(inputPDF);
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setReason(sigReason);
signature.setLocation(sigLocation);
Calendar cal = Calendar.getInstance();
cal.setTime(forcedDate);
signature.setSignDate(cal);

SignatureOptions signatureOptions = new SignatureOptions();
// 预留足够的PKCS7容器空间,建议按实际大小调整
signatureOptions.setPreferredSignatureSize(16384);
doc.addSignature(signature, signatureOptions);

// 2. 单次获取待签名内容
ExternalSigningSupport externalSigningSupport = doc.saveIncrementalForExternalSigning(null);
byte[] contentToSign = IOUtils.toByteArray(externalSigningSupport.getContent());
MessageDigest md = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
byte[] hashToSign = md.digest(contentToSign);

// 3. 调用外部服务获取签名,注意要求外部服务返回完整PKCS7容器,而非单纯签名值
String hashForAMA = SafePdfHelper.getHashtoSign(hashToSign);
String signatureB64 = SafeAmaHelper.getAssinat(token, hashForAMA, "tst_nunommc", credentialID).getSignatures().get(0);
byte[] pkcs7Signature = Base64.getDecoder().decode(signatureB64);

// 4. 直接写入签名到输出流,无需再次调用save方法
FileOutputStream fosSigned = new FileOutputStream("C:/INTEGRACOES/Ama/omitf/tst_signed.pdf");
externalSigningSupport.setSignature(pkcs7Signature);
IOUtils.copy(externalSigningSupport.getContent(), fosSigned);
fosSigned.close();
doc.close();

额外校验点

  • 确认SafePdfHelper.getHashtoSign方法的输出格式和AMA服务要求的哈希输入格式完全匹配,需确认是Base64编码、十六进制编码还是原始字节。
  • 若AMA服务仅返回裸签名值,需要自行使用BouncyCastle封装为PKCS7容器,补充签名证书链、哈希算法标识等必填信息。
  • 可使用PDFBox自带的SignatureUtils工具校验生成的PDF签名结构,快速定位格式问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:09:03