使用摘要异步签署pdf [英] Sign pdf asynchronously using digest

查看:55
本文介绍了使用摘要异步签署pdf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to do the following setup for signing pdfs, broken down into asynchronous steps between a client and a server:

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

我主要基于PDF签名摘要从文件摘要创建 pkcs7 签名

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

The second question allowed me to write most of the code, however I'm getting that the integrity of the file has been compromised. I can't seem to serialize the intermediary pdf for embedding the signature later (to make sure no timestamps are altered, etc). But from the first SO question, it seems to be a harder problem than I thought. Can it actually be done?

我正在使用 pdfbox.

I'm using 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

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

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:

        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,以便稍后在服务器上反序列化并添加客户端的签名?

This setup ends up with the integrity of the file being corrupted, since I'm creating a new PDSignature once I have the encodedSignature on the server to embed it. Is there a way to serialize the PDDocument created after calling addSignature, so I can later deserialize it on the server and add the client's signature?

推荐答案

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

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

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

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

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

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

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.

按照规范的建议,PDFBox 尝试为每个 PDF 修订版提供唯一 ID.但是,就目前的情况而言,我们在执行上述步骤时都需要相同的修订 ID.

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.

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

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

由于我们不希望在签署同一文档时始终使用相同的修订 ID,而只是在当前签署事务期间使用相同的修订 ID,因此我们应该仅在同一事务中使用相同的种子值.由于种子值很长,我们可以简单地使用与上面已经讨论过的 date 相对应的时间(以毫秒为单位),即:

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());

这篇关于使用摘要异步签署pdf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆