I'm using iText 7.1.15 and SignDeferred to apply signatures to pdf documents. SignDeferred is required since the signature is created PKCS11 hardware token (usb key).
When i sign a "regular" pdf, e.g. created via word, i can apply multiple signatures and all signatures are shown as valid in the adobe acrobat reader.
If the pdf was created by combining multiple pdf documents with adobe DC, the first signature is valid but becomes invalid as soon as the seconds signature is applied.
Document in Adobe reader after the first signature is applied:
Document in Adobe reader after the second signature is applied:
The signatures of the same document are shown as valid in foxit reader.
I've found a similar issue on stackoverflow (multiple signatures invalidate first signature in iTextSharp pdf signing), but it was using iText 5 and i'm not sure it is the same problem.
Question: What can i do in order to keep both signatures valid in the Acrobat Reader?
Unsigned Pdf document on which the first signature becomes invalid: https://github.com/suntsu42/iTextDemoInvalidSecondSignature/blob/master/test.pdf
Twice signed document which is invalid: https://github.com/suntsu42/iTextDemoInvalidSecondSignature/blob/master/InvalidDocumentSignedTwice.pdf
Code used for signing
//Step #1 >> prepare pdf for signing (Allocate space for the signature and calculate hash)
using (MemoryStream input = new MemoryStream(pdfToSign))
{
using (var reader = new PdfReader(input))
{
StampingProperties sp = new StampingProperties();
sp.UseAppendMode();
using (MemoryStream baos = new MemoryStream())
{
var signer = new PdfSigner(reader, baos, sp);
//Has to be NOT_CERTIFIED since otherwiese a pdf cannot be signed multiple times
signer.SetCertificationLevel(PdfSigner.NOT_CERTIFIED);
if (visualRepresentation != null)
{
try
{
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
base.SetPdfSignatureAppearance(appearance, visualRepresentation);
}
catch (Exception ex)
{
throw new Exception("Unable to set provided signature image", ex);
}
}
//Make the SignatureAttributeName unique
SignatureAttributeName = $"SignatureAttributeName_{DateTime.Now:yyyyMMddTHHmmss}";
signer.SetFieldName(SignatureAttributeName);
DigestCalcBlankSigner external = new DigestCalcBlankSigner(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signer.SignExternalContainer(external, EstimateSize);
hash = external.GetDocBytesHash();
tmpPdf = baos.ToArray();
}
}
//Step #2 >> Create the signature based on the document hash
// This is the part which accesses the HSM via PCKS11
byte[] signature = null;
if (LocalSigningCertificate == null)
{
signature = CreatePKCS7SignatureViaPKCS11(hash, pin);
}
else
{
signature = CreatePKCS7SignatureViaX509Certificate(hash);
}
//Step #3 >> Apply the signature to the document
ReadySignatureSigner extSigContainer = new ReadySignatureSigner(signature);
using (MemoryStream preparedPdfStream = new MemoryStream(tmpPdf))
{
using (var pdfReader = new PdfReader(preparedPdfStream))
{
using (PdfDocument docToSign = new PdfDocument(pdfReader))
{
using (MemoryStream outStream = new MemoryStream())
{
PdfSigner.SignDeferred(docToSign, SignatureAttributeName, outStream, extSigContainer);
return outStream.ToArray();
}
}
}
}
}
Sample project
I've created a working sample project which uses a local certificate for signing. I also did update iText to version 7.2 but with the same result. It also contains the document which cannot be signed twice (test.pdf) https://github.com/suntsu42/iTextDemoInvalidSecondSignature/tree/master
Edit
I've applied the solution provided by MKL to the sample project on github.
As a second note, It is also possible to use PdfSigner but in this case, the bookmarks of the original document must be removed.