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

Go basic generation is free. Signing is a corporate feature, unlocked by one offline license token. See pricing & licensing.

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.

Do I need a license to sign in Go?

Signing is a corporate feature, so it requires an active license token. Basic PDF generation in Go is free. The same offline Ed25519 token unlocks signing across every language.

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.

Put verifiable signatures into your Go pipeline

One Rust core, the same standards-compliant signatures in every language. Build for free in Go; add a license token to sign and timestamp in production.