IText: cannot set СryptoDictionary property of PdfSignatureAppearance

Viewed 684

There was a code using iTextSharp:

PdfReader reader = new PdfReader(document);
PdfStamper st = PdfStamper.CreateSignature(reader, new FileStream(document + "_signed.pdf", FileMode.Create, FileAccess.Write), '\0');                        
PdfSignatureAppearance sap = st.SignatureAppearance;

// something

PdfSignature dic = new PdfSignature(filterName, PdfName.ADBE_PKCS7_DETACHED);
sap.CryptoDictionary = dic;

I need to write it using iText7:

PdfReader reader = new PdfReader(@"C:\Users\RakuVIu\Documents\rozha.pdf");
PdfSigner signer = new PdfSigner(reader, new FileStream(document + "_signed.pdf", FileMode.Create), new StampingProperties());
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();

// something

PdfSignature signature = new PdfSignature(filterName, PdfName.Adbe_pkcs7_detached);
appearance.SetCryptoDictionary(signature); // no such method!

So, I cannot set CryptoDictionary property, because there is no method or property to do it.

2 Answers

The iText 7 signing API attempts to hide implementation details which shouldn't be used anymore since the 5.3.x signature API overhaul, and the signature dictionary is such a detail.

For details on the signature API introduced in the 5.3.x versions, please read the iText Digital Signatures white paper. The Java examples in there have been ported to C# and can be accessed here.

I'm a bit late to this party but we had the same problem when migrating from iTextSharp to iText 7. We use a dictionary to store extra metadata about a signature. Luckily there is still support in iText by means of an ISignatureEvent interface. You will have to implement this interface and register it with the PdfSigner object (through a SetSignatureEvent(...) call).

So in short your interface implementation should look like this:

public class ClassThatImplementsISignatureEvent: ISignatureEvent
{
  public void GetSignatureDictionary(PdfSignature sig)
  {
    var dict = (PdfDictionary)sig.GetPdfObject();
    dict.Put(new PdfName("SomeData"), new PdfString("SomeValue"));
  }
}

And of course you will have to register it before you call SignDetached() or SignExternalContainer():

PdfSigner signer = new iText.Signatures.PdfSigner(...);
...
signer.SetSignatureEvent(new ClassThatImplementsISignatureEvent());
...
signer.SignDetached(...)
Related