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:
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.
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.
sign
call uses the same file for input and output. This cannot work. Furthermore, you want to add two signatures with certification levels. But only the first signatures – mkl