Sign pdf asynchronously using digest

只愿长相守 提交于 2021-02-06 09:32:10

问题


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

  1. A server receives a pdf and computes it's digest.
  2. Server sends the digest to a client.
  3. Client signs the hash at a later time.
  4. Client sends the signature to server.
  5. Server embeds the signature into the pdf.

I'm basing myself mainly in PDF Signature digest and Create pkcs7 signature from file digest

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?

I'm using pdfbox.

Server code:

        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

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?


回答1:


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


来源:https://stackoverflow.com/questions/46689478/sign-pdf-asynchronously-using-digest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!