4

I'm developing a web application that lets users download a PDF file which they have to sign with Adobe Acrobat using their certificate and then upload back to the web.

I'm using C# and itextsharp 5.5.9.0 for all PDF-related work.

Now, I need to check that the document was not altered after it was downloaded from the web. I was trying to do that by adding my own signature to the PDF file before letting the users download it (signing implemented more or less like in this question). The signing and verification works fine until the file is signed for the 2nd time (with the user's certificate).

After that the first signature somehow becomes invalid, I checked both with itextsharp's AcroFields.SignatureCoversWholeDocument method (it returns false) and in Adobe Acrobat UI (screenshot).

So, I have 2 questions:

  1. Is it at all possible to check whether the document was modified between the 2 signatures were applied?
  2. If not - what's the alternate way to programmatically (using itextsharp) check whether the PDF file was changed after it was generated and before it was signed?
Community
  • 1
  • 1
Andre Borges
  • 1,360
  • 14
  • 37
  • Can you share sample pdfs, one with only your signature and one with that plus an additional signature damaging yours? – mkl Aug 02 '16 at 20:59
  • @mkl, sure, [here they are](https://dl.dropboxusercontent.com/u/21119693/pdfs.zip) – Andre Borges Aug 03 '16 at 07:40
  • The second signature has not been added in append mode. Not using append mode automatically invalidates existing signatures. – mkl Aug 03 '16 at 10:29
  • @mkl, thank you, I added the `append` param to `PdfStamper.CreateSignature` method, and now Acrobat shows both signatures are valid. However, `AcroFields.SignatureCoversWholeDocument` still returns `false` for the 1st signature. How do I validate the document hasn't been midified after the 1st signature was applied? – Andre Borges Aug 03 '16 at 11:11
  • The first signature *cannot* cover the whole document because the second signature and some PDF objects it is embedded in and referenced by are appended to the original document signed by the first signature. – mkl Aug 03 '16 at 11:58
  • @mkl, so how do validate that nothing was added to the document except those PDF object created by the 2nd signature? – Andre Borges Aug 03 '16 at 12:05

1 Answers1

5

The signing and verification works fine until the file is signed for the 2nd time (with the user's certificate). After that the first signature somehow becomes invalid

As already clarified in comments, if one wants the first signature to remain valid, the second must be applied in append mode (iText lingo) / as an incremental update (PDF specification lingo). Otherwise the signed bytes very likely change and the signed hash value does not match anymore.

  1. Is it at all possible to check whether the document was modified between the 2 signatures were applied?

More exactly your question should be whether it is possible to check if the document modifications between the two signatures are in excess of the changes plausible for embedding the second signature.

In short: It is possible in your use case but still means quite some work and juggling with iText low-level APIs. In detail:

In general this is not trivial because adding a new signature with visualization plausibly

  • changes the annotations of the page in question as the signature visualization is a widget annotation;
  • changes the PDF form definition as the signature is anchored as a form field;
  • may create appearance streams for other form fields to fix their exact appearance in the signed file;
  • may change metadata streams to document the act of signing;
  • may change the digital security store of the document;
  • may change probably even more.

Thus, it is non-trivial to check whether the changes fall in any of those categories or not.

Furthermore you have to check for other cheats, e.g. the signature visualization might cover the whole page and show a manipulated version of that content...

But you say your users

have to sign with Adobe Acrobat

This may make your task somewhat feasible: If you use Adobe Acrobat to add sample signatures to a number of documents you signed first before, you can analyze what Adobe Acrobat usually changes in documents when signing them.

Using this knowledge you can implement a class which checks whether only those changes are present.

  1. If not - what's the alternate way to programmatically (using itextsharp) check whether the PDF file was changed after it was generated and before it was signed?

Without a first signature applied by you the situation becomes much more difficult as there is no reason for the user's PDF signing software to limit the internal structure changes in the document as long as they have no impact on its outward behavior. So I would try working with double signatures.

Alternatively you might try and render the original document and the version signed by your user as bitmaps and compare them. There should only be differences in the area where the user signature visualization is placed. This does not verify the interactive PDF features but at least the integrity of a print output.

Rendering is not yet a feature of iText but the parsing framework meanwhile has evolved far enough to serve as the base for a rendering feature.


Applying a first signature can even help preventing accidental changes: If you provide an empty signature field for the user and use a certification signature yourself, you can limit the "allowed changes" to little more than filling that empty signature field, and Adobe Acrobat usually respects such restrictions unless explicitly told otherwise.


For backgrounds on integrated PDF signatures have a look at this answer on Information Security Stack Exchange.

mkl
  • 90,588
  • 15
  • 125
  • 265
  • There's just one thing I'd like to clarify. Many iText samples ([example](https://sourceforge.net/p/itextsharp/itextsharp/ci/2f27ae3e8099c94b12ddac04637f68f4724aed2a/tree/src/core/iTextSharp/text/pdf/AcroFields.cs#l2185)) say that checking for modifications is done via `PdfPKCS7.Verify()` method. I checked several ways of generating a 2nd signature, and in all cases `Verify()` method returned `true` for the 1st signature as well. Are you suggesting that this method is unreliable and cannot be used for checking modifications with 100% accuracy? – Andre Borges Aug 04 '16 at 06:55
  • Have a look at [this answer](http://security.stackexchange.com/a/35131/16096), in particular the image illustrating [multiple signatures in a PDF](http://i.stack.imgur.com/GKdYw.jpg). `PdfPKCS7.Verify()` applied to the first signature checks whether the range covered by the first signature is untouched. It does not check beyond that! – mkl Aug 04 '16 at 10:18