如何为嵌入式签名时间戳更新PDF的DSS字典并符合DocMDP权限1
问题分析
你遇到的核心问题是:调用saveIncrementalForExternalSigning后,内存中修改的DSS字典无法同步到输出PDF。这是因为该方法已经将当时的文档状态(包含DSS)写入了输出流的增量更新段,后续ExternalSigningSupport.setSignature仅负责写入签名值,不会处理其他文档修改。同时DocMDP权限1限制了签名后不能再做任何增量更新,所以必须把所有修改(签名、完整DSS)放在同一次增量操作中完成。
解决方案
方案一:将时间戳验证信息嵌入CMS签名包(推荐,实现简单)
跳过DSS字典的依赖,把时间戳的证书、吊销信息直接嵌入到CMS签名数据中,PDF阅读器可直接从CMS包内获取所有验证所需信息:
- 在
generateCMSSignedData方法中预留逻辑,支持添加额外证书和CRL; - 获取时间戳令牌后,提取其中的证书链和吊销信息,将其加入CMS的
CertificatesStore和CRLsStore; - 最终生成的带时间戳CMS包会包含签名、时间戳的全部验证信息,无需修改DSS字典即可完成验证。
方案二:预加载TSA固定证书的吊销信息(适用于TSA证书不变的场景)
如果你的TSA服务使用固定的证书链,可提前获取并预加载验证信息到DSS:
- 预先获取TSA的根证书、中间证书(可通过TSA公开接口或配置文件加载);
- 调用
validationService.addValidationInformation将TSA证书的吊销信息添加到DSS; - 再执行
saveIncrementalForExternalSigning、生成签名、获取时间戳等后续流程; - 由于DSS已提前包含TSA的验证信息,后续生成的时间戳可直接被阅读器通过DSS验证。
方案三:手动构建单次增量更新(复杂但精准)
若必须在DSS中包含动态获取的时间戳验证信息,需手动处理PDF增量更新全流程,确保所有修改一次性完成:
- 初始化签名字典,设置DocMDP权限等参数并添加到
PDDocument; - 添加签名的验证信息到DSS;
- 计算待签名内容的哈希(即去除签名值占位符后的文档字节流哈希);
- 生成CMS签名,调用TSA获取时间戳并嵌入CMS;
- 提取时间戳的证书和吊销信息,更新内存中的DSS字典;
- 使用PDFBox低级API(如
COSDocument、WriteIncremental)手动生成增量更新段,将更新后的DSS、签名值一次性写入输出流,确保所有修改在同一次增量操作中完成。
内容的提问来源于stack exchange,提问作者Qazazazaz
相关产品推荐
相关产品推荐

