How to Add Multiple Signatures on a PDF Document Using UniPDF
Adding multiple signatures to a PDF document is essential for documents that require approval from multiple parties. Whether you need to sign a contract, an agreement, or any other official document, having multiple signatures on a PDF is a must for a seamless and legally binding process.
In this guide, we’ll show you how to add multiple signatures on a PDF using UniPDF, a powerful and flexible PDF processing library. The steps below explain how to append multiple signature fields to a PDF, including code samples to make the process clear and straightforward.
Why Add Multiple Signatures on a PDF?
Adding multiple signatures on a PDF is often necessary for documents that require multiple levels of approval or validation. This can include contracts, agreements, legal documents, or any paperwork that involves more than one signer.
Here’s why you might need to add multiple signatures:
Legal Compliance: Documents with multiple signers may be legally binding, ensuring that all involved parties agree to the terms.
Multi-Step Approval: Some documents go through several stages of review and approval, requiring different signers at each step.
Team Collaboration: Business documents may need to be signed by different team members across departments, ensuring proper collaboration.
If you’re wondering how to add multiple signature blocks to a PDF or get additional signatures on a document, the steps below will help you achieve that.
Setting Up Your Environment
Before diving into the process of adding multiple signatures, make sure you have the necessary environment set up. The following steps will guide you through the setup:
1. Get Your API Key
To use the UniPDF SDK, you need an API key from your UniCloud account. This key allows you to access the functionalities provided by the library. Make sure to sign up on the UniCloud website and get your API credentials.
2. Set Up a Local Development Environment
If this is your first time using UniPDF SDK, you’ll need to set up a local development environment. Follow the steps below to clone the project repository and configure the necessary environment variables.
3. Clone the Project Repository
In your terminal, run the following command to clone the UniPDF examples repository:
git clone https://github.com/unidoc/unipdf-examples.git
Navigate to the signatures
folder within the cloned repository:
cd unipdf-examples/signatures
4. Configure Environment Variables
Set your license key using the following command. Replace UNIDOC_LICENSE_API_KEY
with your actual API key:
For Linux/Mac:
export UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE
For Windows:
set UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE
How to Add Multiple Signatures on a PDF Using UniPDF
To add multiple signatures to a PDF document, we will use Go programming language along with UniPDF. Here, we provide a step-by-step guide to achieving this.
Step 1: Understand How the Code Works
The code provided below showcases how to append a new page with a signature to a PDF document. It utilizes a private/public key pair to sign the file.
Code Overview
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"io/ioutil"
"log"
"math/big"
"os"
"time"
"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/annotator"
"github.com/unidoc/unipdf/v3/core"
"github.com/unidoc/unipdf/v3/model"
"github.com/unidoc/unipdf/v3/model/sighandler"
)
The code snippet above imports the necessary packages for creating a signature and appending it to a PDF document.
Step 2: Initialize the UniPDF Library
The following function ensures that your API key is set up before using the UniPDF library:
func init() {
err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
if err != nil {
panic(err)
}
}
This code authenticates the UniPDF library requests by loading the API key from the system environment.
Step 3: Add a Signature to the PDF Document
The main function handles the signing process:
func main() {
args := os.Args
if len(args) < 3 {
log.Fatalln("Usage: go run pdf_sign_twice_visible_annotation INPUT_PDF_PATH OUTPUT_PDF_PATH")
}
inputPath := args[1]
outputPath := args[2]
f, err := os.Open(inputPath)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
defer f.Close()
pdfReader, err := model.NewPdfReader(f)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Add the first signature
buf, err := addSignature(pdfReader, 0)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Read the updated document
pdfReader, err = model.NewPdfReader(bytes.NewReader(buf))
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Add the second signature
buf, err = addSignature(pdfReader, 1)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Save the signed PDF
err = ioutil.WriteFile(outputPath, buf, 0666)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
log.Printf("PDF file successfully saved to output path: %s\n", outputPath)
}
The code above adds two signatures to the PDF document by calling the addSignature
function twice, which signs the document and then saves it.
Step 4: Adding the Signature Using addSignature
The addSignature
function adds a signature field to the PDF:
func addSignature(pdfReader \*model.PdfReader, signNumber int) ([]byte, error) {
totalPage, err := pdfReader.GetNumPages()
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
appender, err := model.NewPdfAppender(pdfReader)
if err != nil {
return nil, err
}
priv, cert, err := generateSigKeys()
if err != nil {
return nil, err
}
handler, err := sighandler.NewAdobePKCS7Detached(priv, cert)
if err != nil {
return nil, err
}
signature := model.NewPdfSignature(handler)
signature.SetName("Test Signature Appearance Name")
signature.SetReason("TestSignatureAppearance Reason")
signature.SetDate(time.Now(), "")
if err := signature.Initialize(); err != nil {
return nil, err
}
opts := annotator.NewSignatureFieldOpts()
opts.FontSize = 8
opts.Rect = []float64{float64(50 + signNumber*100), 250, float64(150 + signNumber*100), 300}
opts.TextColor = model.NewPdfColorDeviceRGB(255, 0, 0)
sigField, err := annotator.NewSignatureField(
signature,
[]\*annotator.SignatureLine{
annotator.NewSignatureLine("Name", "John Doe"),
annotator.NewSignatureLine("Date", "2024.10.15"),
annotator.NewSignatureLine("Reason", fmt.Sprintf("Test sign #%d", signNumber)),
annotator.NewSignatureLine("Location", "London"),
},
opts,
)
if err != nil {
return nil, err
}
sigField.T = core.MakeString(fmt.Sprintf("New Page Signature %d", signNumber))
if err = appender.Sign(totalPage, sigField); err != nil {
log.Fatalf("Fail: %v\n", err)
}
buf := &bytes.Buffer{}
if err = appender.Write(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
Step 5: Generating Signature Keys
The generateSigKeys
function creates a private/public key pair:
func generateSigKeys() (*rsa.PrivateKey, *x509.Certificate, error) {
var now = time.Now()
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "any",
Organization: []string{"Test Company"},
},
NotBefore: now.Add(-time.Hour),
NotAfter: now.Add(time.Hour _ 24 _ 365),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
certData, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
if err != nil {
return nil, nil, err
}
cert, err := x509.ParseCertificate(certData)
if err != nil {
return nil, nil, err
}
return priv, cert, nil
}
Step 6: Run the Code
To run the code and add multiple signatures to a PDF, use the command below:
go run pdf_sign_twice_visible_annotation.go sample.pdf signed_sample.pdf
Replace sample.pdf
with the path of your input file and signed_sample.pdf
with the desired output file name.
Conclusion
Adding multiple signatures to a PDF using UniPDF and Go language is straightforward. By following the steps above, you can successfully implement a solution that allows for multiple levels of approval in your PDF documents. This method ensures legal compliance, ease of collaboration, and proper document management.