使用摘要异步签名pdf

时间:2017-10-11 13:28:23

标签: java pdf pdfbox pkcs#7

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

  1. 服务器接收pdf并计算它的摘要。
  2. 服务器将摘要发送给客户端。
  3. 客户端稍后签署哈希值。
  4. 客户端将签名发送给服务器。
  5. 服务器将签名嵌入到pdf中。
  6. 我主要以hourPDF Signature digest

    为基础

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

    我正在使用pdfbox。

    服务器代码:

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

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

    encodedSignature

    此设置最终导致文件的完整性被破坏,因为我在服务器上安装了{{1}}后创建了一个新的PDSignature来嵌入它。有没有办法序列化调用addSignature后创建的PDDocument,所以我以后可以在服务器上反序列化它并添加客户端的签名?

1 个答案:

答案 0 :(得分:2)

What I'm basically doing is sending that digest to the client to sign and then on the server redoing the above steps and setting the client signature

If you want those above steps to generate identical documents, you need to

  • make sure the inputs to those steps are identical and
  • provide the same revision id seed value.

If you do so, the outputs of the above steps are identical as is required for your task.

Making sure the inputs are identical

One step of your above steps is prone to result in different inputs:

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

To guarantee identical inputs, you have to determine date only once and use that single value every time you execute those steps for the same signing transaction.

Providing the same revision id seed value

As recommended by the specification, PDFBox attempts to give each PDF revision its unique ID. In the case at hand, though, we need the same revision ID both times the above steps are executed.

Fortunately, PDFBox allows us to provide the seed value it uses to make the revision ID unique enough.

As we don't want to same revision ID all the time we sign the same document but merely during the current signing transaction, we should use the same seed value only in the same transaction. As the seed value is a long, we can simply use the time in milliseconds corresponding to the date already discussed above, i.e.:

pdDocument.setDocumentId(date.getTimeInMillis());