Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pdfbox signing - saveIncremental vs saveIncrementalForExternalSigning

I'm working on signing pdf file, and I get some concerns. From pdfbox example, I see 2 ways to do sign pdf. The first is:

document.saveIncremental(output);

And the second way:

ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fos);
// invoke external signature service
byte[] cmsSignature = sign(externalSigning.getContent());

if (isLateExternalSigning()) {
    // this saves the file with a 0 signature
    externalSigning.setSignature(new byte[0]);
    // remember the offset (add 1 because of "<")
    int offset = signature.getByteRange()[1] + 1;
    // now write the signature at the correct offset without any PDFBox methods
    RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
    raf.seek(offset);
    raf.write(Hex.getBytes(cmsSignature));
    raf.close();
} else {
    // set signature bytes received from the service and save the file
    externalSigning.setSignature(cmsSignature);
}

What are the differences between saveIncremental and saveIncrementalForExternalSigning? I mean the use cases of these methods.

What are the purposes of each method?

What is "incremental"?

What is "external signing"? Is it third party like government?

like image 735
SoT Avatar asked Dec 19 '20 14:12

SoT


1 Answers

What is "incremental"?

When saving changes to a pdf, one has two choices, one can save a completely new pdf file or one can append the changes to (a copy of) the original file. The latter technique is called an incremental update.

When signing an already signed pdf again the additions for this new signature must be applied as incremental update to prevent invalidating the already existing signatures:

sketch of pdf with multiple signatures

(See this answer for backgrounds and references.)

Thus, pdf libraries need to support signing PDFs also in incremental updates.

PDFBox, to keep it simple, supports signing PDFs only in incremental updates, so already a first signature is added that way.

What are the differences between saveIncremental and saveIncrementalForExternalSigning?

saveIncremental

Creating a signed pdf with saveIncremental employs a callback to generate the signature container: the method sign of the SignatureInterface implementation you chose in your PDDocument.addSignature call is used by saveIncremental to retrieve a signature container for the document bytes to sign.

In the pdfbox signing examples the sign method is implemented in CreateSignatureBase and it is set as signature interface in signPDF.

saveIncrementalForExternalSigning

Creating a signed pdf using saveIncrementalForExternalSigning does not require a SignatureInterface implementation. Instead it returns an ExternalSigningSupport object from which you can retrieve the data to sign (getContent) for which in turn you can then create a signature container which you eventually can inject into the pdf using another ExternalSigningSupport method (setSignature).

So far this only sounds like an option to support different programming pattern preferences, callback versus non-callback, sequential.

There is an additional option here, though, also known as deferred signing: instead of injecting an actual signature container you can inject a dummy:

externalSigning.setSignature(new byte[0]);

and retrieve the position where the placeholder for the signature container (in hex encoding) is located:

int offset = signature.getByteRange()[1] + 1;

Thus, now you can calculate the hash to sign, store away the file and that offset in e.g. a database, and call some signing service without having to hold the pdf in memory.

Eventually you can inject the signature container as in the example code:

RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
raf.seek(offset);
raf.write(Hex.getBytes(cmsSignature));
raf.close();

the use cases of these methods

As said above, at first glance the two methods merely support different programming patterns, callback and sequential.

The additional option, though, indeed allows support of additional use cases, it is especially handy in some situations:

  • if the signing service is slow, e.g. because requests are collected and processed in batches or because confirmation of a second factor is awaited.

  • if the retrieval and injection of the signature container shall take place in a different program, probably even a different computer, than the preparation of the pdf.

What is "external signing"? Is it third party like government?

"External" here refers to the program execution. While a callback feels very internal, separation of calls in a sequential order feels less so, and deferred signing can be seen as really external.

Third party signing services (be they government or not) can be integrated in either architecture. Depending on their performance, a deferred approach might be preferable.

like image 66
mkl Avatar answered Sep 21 '22 18:09

mkl