替换PDF中的签名内容

时间:2013-02-12 11:13:04

标签: java pdf itext

如何在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中打开文档时)被破坏。

1 个答案:

答案 0 :(得分:2)

当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响应后,您可能会感到惊讶, Adob​​e Reader使用这些信息进行验证。在根据ISO-32000-1的集成PDF签名的上下文中,第12.8.3.3节 PKCS#7在ISO 32000中使用的签名

  

PKCS#7对象应包含作为签名属性的撤销信息(PDF 1.6):此属性可能包含执行撤销检查所需的所有撤销信息签名者证书及其签发人证书。由于吊销信息是签名属性,因此必须在计算数字签名之前获取这意味着签名者使用的软件必须能够构建证书路径和相关的吊销信息。如果无法获得其中一个元素(例如,无法连接),则无法使用具有此属性的签名。