How to apply digital signatures with UniPDF
“Electronic signature” covers anything that records intent to sign, down to pasting a scan of your handwriting onto a page. A digital signature is the cryptographic subset: a private key and an X.509 certificate are bound to the exact bytes of the document, so a validator can report who signed and whether a single byte changed afterwards. UniPDF produces digital signatures. The visible mark is optional and drawn separately.
You need a key and certificate, a model.PdfAppender over the document, and a
handler:
handler, err := sighandler.NewAdobePKCS7Detached(priv, cert)
if err != nil {
return err
}
signature := model.NewPdfSignature(handler)
signature.SetName("John Doe")
signature.SetReason("Approved")
signature.SetDate(time.Now(), "")
if err := signature.Initialize(); err != nil {
return err
}
opts := annotator.NewSignatureFieldOpts()
opts.Rect = []float64{10, 25, 75, 60}
field, err := annotator.NewSignatureField(signature,
[]*annotator.SignatureLine{annotator.NewSignatureLine("Name", "John Doe")}, opts)
if err != nil {
return err
}
if err := appender.Sign(1, field); err != nil {
return err
}
return appender.WriteToFile("signed.pdf")signature.Initialize() has to run before you write the file. It is where the
handler reserves space in the PDF for the signature bytes, and skipping it
leaves nothing for the signature to go into.
The appender is the part that surprises people. model.NewPdfAppender needs a
reader built on a seekable source, one implementing both io.ReadSeeker and
io.ReaderAt, because it writes an incremental update on top of the original
bytes rather than regenerating the file. An *os.File or a *bytes.Reader
works. Feeding the signed output back through model.PdfWriter rewrites those
bytes and breaks the signature, so keep signing as the last step.
The page number in appender.Sign is 1-based.
Which handler you choose sets the format. NewAdobePKCS7Detached is the usual
starting point; the NewEtsiPAdES* family produces PAdES signatures at levels
B-B through B-LTA. The signing overview compares them.
For a full runnable program, see Sign with PKCS12 File, or Validating Digital Signature for checking the result.