dealfonso / sapp

Simple and Agnostic PDF Document Parser in PHP - sign PDF docs using PHP
GNU Lesser General Public License v3.0
110 stars 29 forks source link

Can't add multiple signature appearance at once. #47

Open Guervyl opened 1 year ago

Guervyl commented 1 year ago

Hi, It would be great if I can add multiple signature appearance at once.

The problem is, if I add a signature, save the pdf and add another one, The pdf signature is now invalid because after signing, modification is not allowed. That's the whole point of signing a document with a digital signature.

fredsal commented 1 year ago

Feel free to make a PR adding that feature

Guervyl commented 1 year ago

Sorry, I don't understand the meaning of PR

dealfonso commented 1 year ago

Hi, The concept of signing the document forces only one signature can be added at once. But you should be able to sign a document multiple times, one after the other; in fact, this is one of the points of this library. An example of adding two signatures would be the next:

$file_content = file_get_contents($argv[1]);
$obj = PDFDoc::from_string($file_content);
$obj->set_signature_certificate("path_to_certfile1", $password1)
$docsigned = $obj->to_pdf_file_s();
$obj2 = PDFDoc::from_string($doc_signed);
$obj2->set_signature_certificate("path_to_certfile2", $password2)
$docsigned2 = $obj2->to_pdf_file_s();
echo $docsigned2
dealfonso commented 1 year ago

I'm sorry, but I think I did not read the question properly...

The PDF document cannot add multiple signature appearances for one single digital signature. It is possible to embed a whole object, but this library does not support it. The idea is to add a more complex signature (e.g. add some text), but it is not possible at this time, because the library has no support for creating text. This is one of the future works, but it is not a priority, now.

Guervyl commented 1 year ago

Hi, Actually the library is already doing the work. I managed to modify the code to make _appearance an array. But as I don't know how the pdf signing code works, it adds the images to the pdf. But even if I loop over the certificates to repeat the process in to_pdf_file_b, it only adds the latest certificate to the pdf and leave a placeholder to add the missing certificates. After I export it to pdf, Adobe allow me to add the missing certificates and the PDF is still valid. There was no alert that there were changes in the PDF after first signing.

Guervyl commented 1 year ago

Reading the method _generate_signature_in_document comments I can see you said the same thing I wrote. But why isn't it possible to call _generate_signature_in_document again to add the other signature without saving the PDF?

dealfonso commented 1 year ago

Hi,

well, you do not need to save the document. As in the example I gave you in a previous comment, you can use $docsigned = $obj->to_pdf_file_s(); to create a new document in-memory.

The reason why I separated the creation of a signature from the eventual next one is to make sure that the user of the library understands the concept of signing a PDF document: when you sign a document using one certificate, you are making a photo of that document saying "I certify that this document has exactly this content". If you add a new signature, It would mean something like "I certify that this document has exactly this content and a certificate". That needs two steps: one certificate and the other. (*) giving an appearance like an image or a text is an extended feature that offers the digital signature.

I think that your reasoning is about having a so-called function like sign_document that will return a signed document, but it would only be syntactic sugar, because you'll simply have to call the combination of both calls. I'll work on that function and will create a new release... but as I said, it is as simple as copying the example pdfsigni.php.

dealfonso commented 1 year ago

Hi,

I added the function sign_document to the PDFDoc object. This is a shortcut to generate a signed document using a signature appearance and a certificate. So now you can chain signatures...

$certificates = [ ... ]
foreach ($certificates as $certificate) {
  $document = $document->sign_document($certificate);
}
echo $document->to_pdf_file_s();

Please, check if that solver your problem.

Guervyl commented 1 year ago

Hi @dealfonso, Thanks for your reply.

I already had a function like sign_document. What it did globally is add a certificate, save the pdf in memory and add the other certificate. It did exactly what you said I certify that this document has exactly this content and a certificate. The problem is, as you can see from acrobat, the first certificate is marked as invalid because the document has changed.

pdf altered

So, what I want is to add multiple signatures without altering the PDF first signatures to just say "We certify that this document has exactly this content". Look at this PDF, I modified the code to add the first certificate and let the second one as a placeholder by calling just _generate_signature_in_document after calling set_signature_appearance then set_signature_certificate. I just added the first certificate and add a placeholder to insert the second certificate from Acrobat:

not-altered

As you can see in the image, From Acrobat I selected the second certificate to fill the empty one, Acrobat allow me to save a new PDF and the magic is that the first certificate is still valid like if the document have never been modified. This is what I need to do from coding.

I understand this is not a priority for you, but, I really need this feature. If you could explain what does your code from line 700 in to_pdf_file_b(...) do so that I can implement this feature it would be a great help.

dealfonso commented 1 year ago

Hi, now I see what is happening... for some reason, I think that the code is adding some characters that mess the result. I need to debug it...

Guervyl commented 1 year ago

Hi @dealfonso,

Could you solve the problem please?

dealfonso commented 1 year ago

Hi,

Sorry but no. Moreover, I found that it depends on the original document. I found that documents coming from Windows are prone to this problem.

fredsal commented 1 year ago

Sorry, I don't understand the meaning of PR

PR means Pull Request, you can make a debug to find the problem, then you make a PR with the fix here

about-pull-requests creating-a-pull-request