Skip to content
How to apply digital signatures with UniPDF

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.

Last updated on