使用 ESIG/DSS 将数字签名添加到具有可见时间戳和原因字段的 PDF

adding digital signature to PDF with visible timestamp and Reason field using ESIG/DSS

我正在尝试理解并实施基于欧盟委员会发起的解决方案 Digital Signature Service project。我目前已经在Nowina NexU客户端软件的帮助下成功使用了前面提到的github link中提到的DSS-DEMO应用程序提供的抽象。我的愿望是使用以下配置对 PDF 文档进行数字签名:

我希望签名有一个可见的部分,即在文档的第一页上可以看到。这在一定程度上得到了证明 here。就个人而言,我需要实际的签名时间戳和证书中的签名者姓名。在上面的演示中,这是通过向签名函数提供 "parameters" 来完成的。

我还想填写签名的原因字段 - 随后当您使用 Adob​​e Acrobat 等程序查看签名属性时会显示该字段 Reader。

到目前为止我的问题如下,我似乎既找不到示例也找不到关于它们的其他信息。

  1. 如果我想显示我将从 Timestamp Authority 服务获得的签名时间戳,我将如何获得它,因为与时间戳服务器的通信是在签名过程中完成的,即在指定参数之后上面提到。我想我必须深入研究 DSS 代码并自己完成所有步骤。
  2. 目前,一件奇怪的事情发生了。当我指定一个硬编码的原因(如 'testtest')或根本没有任何原因时,签名似乎被认为是有效的,或者至少是未知的。当我用其他东西的结果填充它时,签名无效。因为像这样的事情通常不会靠魔法发生,所以我一定是做错了什么。

代码的组织大致如下 - 两台机器之间存在 REST 通信 - 服务器和安装了 NexU 的客户端。 NexU 与客户端计算机上的智能卡或任何其他证书存储进行所有通信 - 它与服务器交换摘要值和签名摘要值。服务器代码中有两个特定阶段:

我为这两个阶段提供了大量参数,其中包括指定签名时间戳、原因和我希望出现在第一页上的文本的视觉参数。我正在为两个阶段使用相同的参数(因为我不确定我应该在哪个阶段给出哪个)

我的签名日期 - 尽可能接近时间戳授权服务器的时间戳不是合乎逻辑的吗?好的 - 我将其设置为签名过程开始时我自己的服务器的当前时间戳。

我正在使用 PAdESSignatureParameters.setReason 设置 Reason。 感谢任何有用的见解 - 谢谢。

  1. 我已经解决了签名的原因字段的奇怪问题。
  2. 我似乎没有看到任何关于签名日期与时间戳机构提供的时间戳不同的方法。

解释如下。

第一种情况,是我的错。详细来说,根据我的理解,签名参数使用 SigningService.fillParameters() 方法两次提供给 DSS 方法。

  1. 在 SigningService.getDataToSign(...) 然后
  2. 在 SigningService.signDocument(...)

这在两种方法中都很重要,因为在第一次计算待签名文档的hash/digest。由于我选择了要封装的签名,即包含在要签名的文档中,我们需要先应用签名,然后根据该 "final" 文档计算摘要。

据我在 DSS 代码中看到的(大约),上传的 PDF 的内存表示已签名,并在 getDataToSign 期间计算其摘要 - 但结果被丢弃。

在实际的 signDocument 方法期间(在此期间,摘要已经返回到安装了 NexU 的客户端,并返回到已签名的服务器),上传的 PDF 再次被签名,其摘要再次计算,但这次实际签名的摘要(我们从客户那里得到)也被应用于文档——并且这个操作的内存中结果作为签名的 PDF 文档发送回客户。

我做错的是,在第一次时,我丢失了我要添加为 Reason 的变量(它丢失在模型属性的某处 - 我没有在请求之间的某处传递它),结果是我传递给 getDataToSign 的第一个参数映射与第二个参数映射不同——所以这只是合乎逻辑的,文档的实际 hash/digest 与保存的签名中的摘要不同(因为在计算要签名的摘要时,我没有传递原因)。这就是为什么当我传递硬编码值时,因为它是硬编码的,所以它在两次调用 fillParameters 期间都存在。这是一个多么愚蠢的错误,我知道。我早该知道这一点,因为将 Reason(或 Location 等其他字段)传递给 Signature 绝对没有任何困难。

顺便说一句,签名是使用 Apache PDFBox 完成的,并且是增量完成的。

至于第二件事,我们决定保持原样,尽管签名时间戳和时间戳权威之间有一个比较可观的差距。我真的不知道在这种情况下允许的差距应该是多少。我猜这是因为

  1. 我的服务器当地时间可能有点不正常
  2. 因为整个签名过程是在两台机器(安装了 NexU 的服务器和客户端,以及智能卡)之间进行的,并且因为有不同的对话框 windows 出现要求输入密码等。 - 这一切都推迟了实际的签名,并且在最后一步完成了对时间戳授权的调用。当然,我不确定这是否是一个问题,因为理论上时间戳权威不知道被更改的实际内容 - 在这种情况下会触发先前的错误..

更像是 - 当然,我愿意接受其他评论和答案。谢谢!