如何在iText中完成此操作?我有一个带有客户签名的PDF。我需要向未签名的属性添加ocsp响应。
我知道如何使用
org.bouncycastle.cms.CMSSignedData.replaceSigners(...).getEncoded()
但我不知道如何使用
PdfName.CONTENTS
替换PDF中的new PdfString(newSignature).setHexWriting(true)
。如果我使用此代码:PdfDictionary other = new PdfDictionary();
other.put(PdfName.CONTENTS, new PdfString(newSignature).setHexWriting(true));
dicSignature.merge(other);
其中
dicSignature
是包含签名的字典,然后签名(在Adobe Reader中打开文档时)被破坏。 最佳答案
当iText在正常模式下使用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签名的上下文中,如ISO 32000中使用的12.8.3.3 PKCS#7签名,
daccess-ods.un.org daccess-ods.un.org PKCS#7对象应包含作为签名属性的撤消信息(PDF 1.6):该属性可能包括执行对签名者证书及其发行者证书的撤消检查所必需的所有撤消信息。由于吊销信息是已签名的属性,因此必须在计算数字签名之前获取它。这意味着签名者使用的软件必须能够构造证明路径和相关的吊销信息。如果无法获得其中一个元素(例如,无法建立连接),则无法使用具有此属性的签名。