Hi Rade,
The timestamp service is called twice because, when signing a PDF file, we must reserve a “hole” in the PDF where the signature will be inserted, and the signature is calculated from the PDF file’s hash, excluding that “hole”.
The reserved “hole” must be large enough to accommodate the entire signature in the CMS format, but not so large that the space in the “hole” after the signature is wasted.
CMS signature includes additional information, beyond just the raw cryptographic signature, such as the signer’s certificate, certificate chain, revocation information, timestamp, etc.
To properly estimate the CMS signature length, if the signature will also contain a timestamp, GemBox.Pdf will initiate a dummy timestamp request just for the purpose of finding the length of the timestamp that is extended by the extra 32 bytes of padding. PdfTimestamp.EstimatedTimestampTokenLength (a property that is available only if you are deriving from a PdfTimestamper) caches and returns that value. Because the value of this property is cached, the timestamp service is called 3 times instead of 4 times in the PDF Advanced Electronic Signatures (PAdES) in C# and VB.NET example:
- To find the estimated timestamp token length that is then cached.
- To timestamp the hash of the raw signature value.
- To timestamp the hash of the PDF file (excluding the “hole” for the document timestamp signature) when adding a document timestamp signature.
If you plan to use the same timestamp service, its timestamp token length should remain relatively stable, so you can avoid an extra call to estimate the timestamp token length by providing a hardcoded estimated timestamp token length.
You do this by deriving from the PdfTimestamper and providing a hardcoded value of the estimated timestamp token length, like in the following code snippet:
class MyPdfTimestamper : PdfTimestamper
{
private readonly int estimatedTimestampTokenLength;
public MyPdfTimestamper(string address, int estimatedTimestampTokenLength) : base(address)
{
this.estimatedTimestampTokenLength = estimatedTimestampTokenLength;
}
protected override int EstimatedTimestampTokenLength => this.estimatedTimestampTokenLength;
}
To find out the estimated timestamp token length to be hardcoded, you can first use the following PdfTimestamper implementation:
class MyPdfTimestamper : PdfTimestamper
{
public MyPdfTimestamper(string address) : base(address)
{
}
protected override int EstimatedTimestampTokenLength
{
get
{
var value = base.EstimatedTimestampTokenLength;
return value;
}
}
}
with the breakpoint on the return value; statement.
Once you get the estimated timestamp token value, hardcode it, and thus reduce the number of calls to the timestamp service by one for each PdfTimestamper(-derived) instance by using MyPdfTimestamper instead of PdfTimestamper in your code.
Regards,
Stipo