How to Add Blank Page in Digitally Signed Pdf Using Java

how to add blank page in digitally signed pdf using java?

To put Joeri's answer into context, have a look at the Adobe technical white paper Adobe Acrobat 9 Digital Signatures, Changes and Improvements, especially its section "Allowed and disallowed changes." Here Adobe clarifies the allowed changes (as seen by Acrobat 9 and up) that can be made to a certified or signed document without invalidating the signatures applied to the document.

Allowed actions for certified documents

Certified with no changes allowed

Allowed

  • No changes allowed

Disallowed

  • Digitally signing
  • Supplying form field values
  • Adding or editing annotations
  • Adding form fields
  • Changing page content

Certified with form fill-in and digital signatures allowed

Allowed

  • Supplying form field values
  • Digitally signing

Disallowed

  • Adding or editing annotations
  • Adding form fields
  • Changing page content

Certified with annotations, form fill-in, and digital signatures, allowed

Allowed

  • Adding or editing annotations
  • Supplying form field values
  • Digitally signing

Disallowed

  • Adding form fields
  • Changing page content

Allowed actions for signed but uncertified documents

Allowed

  • Adding signature fields (see Limitations on adding signature fields to signed but uncertified documents)
  • Adding or editing annotations
  • Supplying form field values
  • Digitally signing

Disallowed

  • Adding form fields other than signature fields
  • Changing page content

As you see "Changing page content" always is in the "Disallowed" category. As adding a page changes page content — afterwards there is at least a white page where there used to be nothing —, this is not allowed.

(Even though not explicitly mentioned here, instantiating page templates most likely also is allowed whenever form fill-ins are allowed as that would conform to the PDF standard, cf. ISO 32000-1 section 12.8.2.2.2. But making use of such page templates would at least require the document to be specially prepared before signing, and your question sounds like the documents are already signed without any such preparation...)

PS: Obviously even these allowed changes need to be added in append mode aka incremental updates. Anything else will break the signature for good. For some backgrounds see this answer.

Adding additional page to signed pdf and sign it again

No, it is not possible. Adding pages to an already signed PDF is not allowed.

In detail

I read in the adobe documentation under incremental updates that it may be possible.

Indeed it is possible to add changes to a PDF without touching the former revision. Thus, if that former revision was signed, the signature mathematically remains valid, it still signs the correct hash value.

But the PDF specification and its main interpretation (by Adobe that is) contain additional restrictions, cf. this stack overflow answer. As you find there at most the following changes are allowed to signed documents:

  • Adding signature fields
  • Adding or editing annotations
  • Supplying form field values
  • Digitally signing

At least Adobe Acrobat (Reader) does test for such changes in addition to the check for mathematical validity even if numerous other validation services don't.

Thus, your task to add additional page to the signed PDF and sign it again without breaking the first signature cannot be implemented.

How to add blank pages in exist PDF in java?

The answer by Dinup Kandel is wrong because it's about creating a document from scratch.

The answer by NK123 is very wrong because it uses PdfWriter/PdfImportedPage to concatenate documents. That example assumes that all pages in the original document have the size A4. This won't always be the case. As documented, this also throws away all interactivity.

The only good answer looks like this:

PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.insertPage(reader.getNumberOfPages() + 1, reader.getPageSizeWithRotation(1));
stamper.close();
reader.close();

If src refers to a document with 10 pages, the code above will add an extra blank 11th page, using the same page size as the first page.

itext 7: Problem save digitally signed document (java)

To apply changes to a signed PDF and keep the signatures cryptographically valid, you have to create an incremental update. In iText lingo that means using append mode. In iText 7 you use append mode by specifying stamping properties accordingly:

PdfDocument pdf2 = new PdfDocument(pdfReader, pdfWritter, new StampingProperties().useAppendMode());

Beware, you only are allowed to apply a small set of changes to a signed PDF, read this answer.

Multiple Signings in pdf File using IText

There are a number of errors in your approach

Your main method

The Original main Code

In your original code your main method contained these two calls:

sign(new FileInputStream(basePath+"nonsigned.pdf"), new FileOutputStream(basePath+"nonsigned.pdf"), new FileInputStream(basePath+"mycert3.p12"), "mycert3".toCharArray(), "something", "something", basePath + "signing1.png");
sign(new FileInputStream(basePath+"nonsigned.pdf"), new FileOutputStream(basePath+"signed.pdf"), new FileInputStream(basePath+"mycert4.p12"), "mycert4".toCharArray(), "something", "something", basePath + "signing2.png");

In particular in your first line you created a FileInputStream and a FileOutputStream for the same file name. Doing the latter truncates the file, so when the code in your sign method attempts to read the file from the former stream, it doesn't find anything and throws an exception.

Thus, you must not use the same file as both input and output of your signing procedure.

The Edited main Code

You then edited your main method to contain these two calls:

sign(new FileInputStream(basePath+"nonsigned.pdf"), new FileOutputStream(basePath+"signed.pdf"), new FileInputStream(basePath+"mycert3.p12"), "mycert3".toCharArray(), "something", "something", basePath + "signing1.png");
sign(new FileInputStream(basePath+"nonsigned.pdf"), new FileOutputStream(basePath+"signed.pdf"), new FileInputStream(basePath+"mycert4.p12"), "mycert4".toCharArray(), "something", "something", basePath + "signing2.png");

Now both calls read the unsigned PDF, sign it, and write the result to the same output file. Thus, the first call creates a PDF with a single signature and the second call also creates a PDF with a single signature and its output overwrites the output of the first call.

Thus, you must use the output of the first signing call as input of the second signing call.

For example like this:

sign(new FileInputStream(basePath+"nonsigned.pdf"), new FileOutputStream(basePath+"signedOnce.pdf"), new FileInputStream(basePath+"mycert3.p12"), "mycert3".toCharArray(), "something", "something", basePath + "signing1.png");
sign(new FileInputStream(basePath+"signedOnce.pdf"), new FileOutputStream(basePath+"signedTwice.pdf"), new FileInputStream(basePath+"mycert4.p12"), "mycert4".toCharArray(), "something", "something", basePath + "signing2.png");

Your sign Method

Having made sure that no signing call uses the same file both as input and output and that the second signing call uses the output of the first call as input, we now run into the issues of your sign method used multiple times. (For one-time use it's ok.)

Signature Field Names

In your sign method you have hard-coded the signature field name:

appearance.setVisibleSignature(new Rectangle(300, 600, 630, 500), 1, "sig");

I.e. each call tries to sign the same signature field. According to the JavaDocs of the setVisibleSignature method you use, though:

/**
* Sets the signature to be visible. It creates a new visible signature field.
* @param pageRect the position and dimension of the field in the page
* @param page the page to place the field. The fist page is 1
* @param fieldName the field name or <CODE>null</CODE> to generate automatically a new field name
*/
public void setVisibleSignature(Rectangle pageRect, int page, String fieldName)

So this method tries to create a new visible signature field. As each field has a distinct name, using the same name twice is an error.

Thus, you must make sure that you use different signature field names. A simple option for that is described in the JavaDoc description of the fieldName parameter: If you use null, iText automatically creates a new signature name. So, simply replace "sig" by null in your code line above.

Certification Signatures

In your sign method you set the certification level like this:

appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);

This causes two issues:

  1. CERTIFIED_NO_CHANGES_ALLOWED means what it says: No changes allowed. Signing a second time is a change. So using this certification level forbids signing again. For details on allowed and disallowed changes to a signed PDF read this answer.

    Thus, you must use a certification level which does not forbid creating the second signature.

  2. A document may only contain a single certification signature and any number of approval signatures (regular signatures without a certification level).

    Thus, you must make sure you set the signature appearance certification level only for your first signing call for the document in question.



Related Topics



Leave a reply



Submit