Digital signatures · Go

Digitally sign a PDF in Go

Add a cryptographic PKCS#7 or PAdES signature to a PDF from Go. rust-pdf signs through a non-destructive incremental update, so the original bytes are preserved and the signature stays verifiable in Adobe Reader, pdfsig and any PAdES validator.

Last updated: 2026-06-29

Why Go needs this

A signed contract leaving a Go service has to prove who approved it and that nothing changed afterwards. Hand-rolling the CMS and ByteRange math in Go is a well-known way to ship signatures that Adobe Reader quietly marks invalid, so most teams reach for an external tool or give up on PAdES.

rust-pdf assembles the detached PKCS#7/CMS by hand to control the ByteRange precisely, supports PAdES B-B plus B-LT and B-LTA for long-term validation, and signs through an incremental update so the original bytes and any earlier signatures stay intact.

You bring the key material from Go: decode a PEM with encoding/pem or open a PKCS#12 with crypto/x509, marshal it to PKCS#8 DER, and pass it with the certificate to Sign. The heavy cryptography then executes in the Rust core, away from Go's reflection and garbage collector.

  • PKCS#7 detached and PAdES B-B, with B-LT and B-LTA for long-term validation.
  • Incremental update: the original file is preserved byte for byte, so earlier signatures stay valid.
  • Bring your own key and X.509 certificate (PKCS#8 DER), or chain to a TSA for timestamps.

Sign a PDF in Go with rust-pdf

Install with go get, then call the same idiomatic API every rust-pdf binding shares. The snippet below is real Go code from the reference docs.

go get github.com/rustpdf/rustpdf-go

Go
pdf, _ := os.ReadFile("contract.pdf")
keyDER, _ := os.ReadFile("signing-key.pkcs8.der")   // PKCS#8 private key (DER)
certDER, _ := os.ReadFile("signing-cert.der")       // X.509 certificate (DER)

signed, err := rustpdf.Sign(pdf, keyDER, certDER, rustpdf.SignOptions{
	Reason: "Approved", Location: "New York",
	Name: "Jane Doe", PAdES: true,
})
if err != nil {
	log.Fatal(err)
}
_ = os.WriteFile("contract.signed.pdf", signed, 0o644)
// Verify in a shell: pdfsig contract.signed.pdf  →  "Signature is Valid."
Validated by: pdfsigopensslqpdf

Everything is free.

Full Go reference in the documentation.

Signing in Go: FAQ

Is the signature legally valid?

rust-pdf produces standards-compliant PKCS#7 and PAdES signatures. Legal validity depends on the certificate you sign with (for example an eIDAS qualified certificate or an ICP-Brasil certificate). The library handles the cryptography and the PDF structure correctly, which is what validators such as pdfsig and Adobe Reader check.

Does it support long-term validation (LTV)?

Yes. After signing you can append a Document Security Store with certificates and CRLs (PAdES B-LT) and an RFC 3161 document timestamp (PAdES B-LTA), all offline. A trusted external TSA and live OCSP fetching are the only parts that need network infrastructure.

Is signing free in Go?

Signing is free, like every feature in rust-pdf.

Can I sign with a PEM or PKCS#12 key in Go?

Yes. Decode a PEM with encoding/pem or open a .p12 with crypto/x509, then marshal the private key to PKCS#8 DER and the certificate to its raw DER bytes. Those are the two inputs Sign expects. The CMS and ByteRange handling then run in the Rust core.