【问题标题】:Sign pdf asynchronously using digest使用摘要异步签署 pdf
【发布时间】:2018-03-23 04:52:26
【问题描述】:

我正在尝试执行以下设置来签署 pdf,分为客户端和服务器之间的异步步骤:

  1. 服务器接收 pdf 并计算其摘要。
  2. 服务器将摘要发送给客户端。
  3. 客户端稍后对哈希进行签名。
  4. 客户端将签名发送到服务器。
  5. 服务器将签名嵌入到 pdf 中。

我主要在PDF Signature digestCreate pkcs7 signature from file digest工作

第二个问题允许我编写大部分代码,但我发现文件的完整性已受到损害。我似乎无法序列化中间 pdf 以便稍后嵌入签名(以确保没有更改时间戳等)。但是从第一个 SO 问题来看,这似乎是一个比我想象的更难的问题。真的可以做到吗?

我正在使用 pdfbox。

服务器代码:

        PDDocument document = PDDocument.load(documentFile);
        PDSignature signature = new PDSignature();
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
        signature.setName("Example User");
        signature.setLocation("Los Angeles, CA");
        signature.setReason("Testing");
        Calendar date = Calendar.getInstance();
        signature.setSignDate(date);
        document.addSignature(signature);

        ExternalSigningSupport externalSigningSupport = document.saveIncrementalForExternalSigning(null);

        byte[] content = IOUtils.toByteArray(externalSigningSupport.getContent());
        MessageDigest md = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
        byte[] digest = md.digest(content); // this is sent to client

我基本上做的是将该摘要发送给客户端进行签名,然后在服务器上重做上述步骤并设置客户端签名:

        ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(fos);
        externalSigning.setSignature(encodedSignature); // encodedSignature is received from client and computed based on the digest sent by the server

此设置最终导致文件的完整性被破坏,因为一旦我在服务器上拥有 encodedSignature 以嵌入它,我就会创建一个新的 PDSignature。有没有办法将调用addSignature后创建的PDDocument序列化,这样我以后可以在服务器上反序列化并添加客户端的签名?

【问题讨论】:

  • 你有完整的例子吗?

标签: java pdf pdfbox pkcs#7


【解决方案1】:

我基本上做的是将该摘要发送给客户端进行签名,然后在服务器上重做上述步骤并设置客户端签名

如果您希望上述步骤生成相同的文档,您需要

  • 确保这些步骤的输入是相同的,并且
  • 提供相同的修订 ID 种子值。

如果您这样做,上述步骤的输出将与您的任务所需的相同。

确保输入相同

上述步骤中的一个步骤很容易导致不同的输入:

Calendar date = Calendar.getInstance();
signature.setSignDate(date);

为保证输入相同,您只需确定一次date,并在每次为同一签名交易执行这些步骤时使用该单一值。

提供相同的修订 ID 种子值

按照规范的建议,PDFBox 尝试为每个 PDF 修订版提供其唯一 ID。不过,在当前的情况下,我们需要在执行 上述步骤 的两次时使用相同的修订 ID。

幸运的是,PDFBox 允许我们提供它用来使修订 ID 足够唯一的种子值。

由于我们不希望在签署同一个文档时始终使用相同的修订 ID,但仅在当前签名交易期间,我们应该仅在同一交易中使用相同的种子值。由于种子值很长,我们可以简单地使用上面已经讨论过的date对应的毫秒时间,即:

pdDocument.setDocumentId(date.getTimeInMillis());

【讨论】:

  • 我刚刚有时间实际尝试一下。我打:不能写签名,在 org.apache.pdfbox.pdfwriter.COSWriter.writeExternalSignature(COSWriter.java:789) 没有足够的空间。我设法通过先前为签名分配空间来解决这个问题,但这是一种与这种初始技术非常不同的方法。
  • “这是一种与最初的技术非常不同的方法。” - 实际上这并没有改变太多原来的方式,只需使用document.addSignature(signature, options)而不是document.addSignature(signature) ; options here needs to be a SignatureOptions` 实例,您在其中将 PreferredSignatureSize 设置为足够高的值...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 2016-01-17
  • 2017-01-23
相关资源
最近更新 更多