Why is SignatureHandler called twice?
The first call is not a real signature. UniPDF has to reserve a fixed-size gap
in the PDF for the signature bytes before it knows how large they will be, so by
default it runs the signing function once with throwaway input purely to measure
the result. That happens in signature.Initialize(). The second call, during
appender.Write, is the one that counts.
Harmless with a local private key, expensive when the handler talks to an HSM or a paid signing API. Every handler that does this has a variant that lets you state the size instead.
For NewAdobeX509RSASHA1Custom, switch to
NewAdobeX509RSASHA1CustomWithOpts and set EstimateSize:
handler, err := sighandler.NewAdobeX509RSASHA1CustomWithOpts(cert, signFunc,
&sighandler.AdobeX509RSASHA1Opts{EstimateSize: true})The name reads backwards at first. EstimateSize: true means estimate the size
from the modulus of the public key in the signing certificate, so your
SignFunc is never called during initialization. Leaving it false, which is
what plain NewAdobeX509RSASHA1Custom does, is what produces the mock signing
call. Because the estimate comes from the certificate’s public key, it only
works for RSA; a non-RSA key returns an invalid public key type error.
AdobeX509RSASHA1Opts.Algorithm is worth setting at the same time, since the
handler otherwise defaults to SHA1.
Timestamp handlers take a byte count rather than a flag:
handler, err := sighandler.NewDocTimeStampWithOpts(timestampServerURL, crypto.SHA512,
&sighandler.DocTimeStampOpts{SignatureSize: 6000})SignatureSize defaults to 4192 when it is zero or negative. If the real
timestamp does not fit, signing fails with model.ErrSignNotEnoughSpace, so
overshoot rather than trim. A few unused bytes in the file cost nothing.
sighandler.NewEmptyAdobePKCS7Detached(signatureLen int) is the same idea taken
further: it reserves the space and produces no signature at all, which is what
the external signing flow uses.