当 iText 在正常模式下使用 a 操作文档时PdfStamper
,它可以(并且经常这样做)重新排列现有的 PDF 对象。这显然破坏了任何现有集成签名的哈希值。此外,必须签名的字节范围会发生变化。这很可能是您的问题。
当 iText 使用PdfStamper
附加模式处理文档时,它会保持 PDF 原样,仅附加其添加和更改。虽然这通常是防止集成签名被破坏的方法,但您不能以这种方式更改签名的内容,因为对于嵌入签名有比一般 PDF 更严格的规则。因此,切换到附加模式并不能解决您的问题。
因此,iText 有一个明确的方法来进行签名插入,而无需更改 PDF:
MakeSignature.signDeferred(PdfReader reader,
String fieldName,
OutputStream outs,
ExternalSignatureContainer externalSignatureContainer)
throws DocumentException, IOException, GeneralSecurityException
它的名字是因为这个方法最初是为延迟签名的用例设计的,即首先准备 PDF 进行签名(即添加哈希字节范围所需的所有字典和其他必要的结构,包括在其中留下一个空白最终将注入签名容器),计算哈希值,并将其发送到其他服务,同时将准备好的 PDF 存储在本地。一旦其他服务返回签名,准备好的 PDF 就会被定位,并使用此方法将检索到的签名插入其中。
与您的用例的唯一区别是间隙中已经存在签名。但是,该签名将在使用时被您更新的签名覆盖signDeferred
。
说了这么多,如果您期望在对未签名属性添加 ocsp 响应后, Adobe Reader 会使用这些信息进行验证,您可能会感到惊讶。在根据ISO-32000-1的集成 PDF 签名的上下文中,第 12.8.3.3 节PKCS#7 Signatures as used in ISO 32000,
PKCS#7 对象应包含 [...] 作为签名属性的吊销信息(PDF 1.6):此属性可能包括对签名者证书及其颁发者证书执行吊销检查所需的所有吊销信息。由于撤销信息是签名属性,因此必须在计算数字签名之前获取。这意味着签名者使用的软件必须能够构建证书路径和相关的撤销信息。如果无法获得其中一个元素(例如无法连接),则无法使用此属性进行签名。