Sign and Configure DocMDP Restriction with Valid Changes

In this guide, the process of signing a PDF document with the DocMDP restriction and adding some valid changes will be explained by following the example code.

Sample Input

sample PDF file

Before you begin

You should get your API key from your UniCloud account.

If this is your first time using UniPDF SDK, follow this guide to set up a local development environment.

Project setup

Clone the project repository

In your terminal, clone examples repository using the following command. It contains the Go code we will be using for this guide.

git clone https://github.com/unidoc/unipdf-examples.git

Then navigate to the signatures folder in the unipdf-examples directory.

cd unipdf-examples/signatures

Configure environment variables

Configure your license key using the following command. Replace the UNIDOC_LICENSE_API_KEY with your API credentials from your UniCloud account.

Linux/Mac

export UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE

Windows

set UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE

The next section will explain the example code.

How it works

The import section, as the name implies imports the necessary UniPDF packages and other Go libraries. The init function, which gets executed before the main function, sets your metered license key by loading it from the system environment.

The main function starts in line 39. In the beginning section of this function, the input and output file destinations are read from the command line arguments. In line 66, a signature is added to the document using the addSignature function. Then in line 76, some changes are added to the document by calling addSomeValidChanges. Following this, the introduced changes are validated in line 81.

The function addSomeValidChanges is used to introduce sample changes using a model.PdfAppender. A new square annotation is created using model.NewPdfAnnotationSquare(). Then the Rect, IC and CA fields are set. After this, the annotation is added to the page. In line 108 using appender.UpdatePage(page), the page is updated with new annotation change.

The ValidateFile function in lines 118-153 is used to validate changes. A model.Permissions is obtained from the PdfReader. Then signature handlers are instantiated using:

inner_handler, _ := sighandler.NewAdobePKCS7Detached(nil, nil)
handlerDocMdp, _ := sighandler.NewDocMDPHandler(inner_handler, docMDPPerm)

handlers := []model.SignatureHandler{handlerDocMdp}

The signature is validated using reader.ValidateSignatures(handlers) in line 144. Finally, by iterating through each validation result, the results are printed.

The addSignature function defined in lines 155-216, adds a signature to the document using a PDF Appender. To add the signature, first it gets the private key and certificate using the generateSigKeys() function. Then a new Adobe.PPKMS/Adobe.PPKLite adbe.pkcs7.detached signature handler is created from the private key and certificate object. A DocMDP handler is then created from the previously created inner handler and mdp.FillFormsAndAnnots using handler, err := sighandler.NewDocMDPHandler(inner_handler, mdp.FillFormsAndAnnots).

In lines 180-188, a new signature object is created and initialized using the following code.

signature := model.NewPdfSignature(handler)
signature.SetName("Test Signature Appearance Name")
signature.SetReason("TestSignatureAppearance Reason")
signature.SetDate(time.Now(), "")

// Initialize signature.
if err := signature.Initialize(); err != nil {
  return nil, err
}

Following this, a new model.PdfFieldSignature object is created using signature and then the document is signed by calling appender.Sign method. Finally, the document is written to file in line 219.

The generateSigKeys function, which is used to generated private key and certificate, is defined in lines 228-264. This function uses the rsa.GenerateKey function to generate the private key. Then x509.CreateCertificate and x509.ParseCertificate functions are used to create the certificate. Finally, the private key and the certificate object are returned from the function.

Run the code

Run the code using the following terminal command.

go run pdf_sign_docmdp_valid_changes.go <INPUT_PDF_PATH> <OUTPUT_PDF_PATH>

Sample output

2023/08/22 18:25:18 PDF file successfully signed
2023/08/22 18:25:18 == Signature 1
2023/08/22 18:25:18 Name: Test Signature Appearance Name
Date: 2023-08-22 18:25:18 +0300 UTC+0300
Reason: TestSignatureAppearance Reason
Location not specified
Contact info not specified
Fields: 1
Signed: Document is signed
Signature validation: Is valid
Trusted: Untrusted certificate
diff is permitted: true
MDP warnings:
	Field New Page Signature was changed in revisions #2
	Field New Page Signature was changed in revisions #2
	Widget annotation New Page Signature was changed in revisions #2
	Square annotation  was added in revisions #2
Done

Signed with DocMDP for Valid Changes

Got any Questions?

We're here to help you.