PDF signing

<< Click to Display Table of Contents >>

PDF signing

Digital signatures and electronic (or handwritten) signatures are two mainstream ways to sign a document. Though handwritten signatures don't provide as much security and authenticity as a digital signature it is still useful and sufficient in many situations. With handwritten signatures security and authenticity can be effectively introduced through application user-authentication, making the document accessible only through the application, and taking the user through specific and controlled work-flow. Also handwritten signatures are simple to implement and use. The ASP.NET document viewer supports inserting handwritten signatures on PDF documents. In this section we cover how this can be done.

 

This topic uses WebForms in the ASP.NET web application to demonstrate the implementation of the PDF signing feature. These instructions can be followed for ASP.NET MVC applications as well.

Enabling the feature

1.Follow the topic on displaying server-side documents to create a new ASP.NET web application that loads and displays a PDF file present on the server. This is the document that will be displayed to the user for inserting a handwritten signature.

2.The handwritten signing feature needs to be enabled on the server in the OnServerStart event handler. To do this follow the topic on Server-side events and override the OnServerStart event.

3.In the OnServerStart event enable the PDF signing feature as shown in the code snippet below.

 

 

  using Gnostice.Controls.ASP;
 
  public class MyServerEventsHandler : ServerEventsHandler
  {
      // The event arguments for all methods below have the following common properties
      // HttpContext - instance of HttpContext class for the current request
      
      // Method called when the server starts up
      public override void OnServerStart(OnServerStartEventArgs serverStartEventArgs) 
      {
          // serverStartEventArgs.ViewerPreferences contains the preferences for the viewer
          // The preferences need to be set when the server starts up and they cannot be 
          // changed after that
          var viewerPreferences = serverStartEventArgs.ViewerPreferences;
         
          // Enable PDF signing feature

          viewerPreferences.Interactivity.AllowSigning = true;

             }

    }
 

 

4.Run the application. The viewer displays the PDF document with an additional toolbar button to apply signatures. This new toolbar button can be used to apply a signature on the document.

 

Note that the signature is actually placed in the PDF when the user saves the document. The updated document can be accessed via the AfterDocumentSave event on the server.

 

The screen-shot below shows the toolbar button for applying signatures.

 

PDFSign_toolbar_button

 

The screen-shot below shows the dialog to create and manage signatures.

 

PDFSign_create_dialog

 

The screen-shot below shows a signature being placed on the document.

 

PDFSign_place_signature_anywhere

 

The user is allowed to place the signature anywhere on the document since we have not defined any specific area for it. It is possible to define one or more placeholders on the document where a user is allowed to place signatures. We will now see how to define signature placeholders.

Signature placeholders

Signature placeholders can be specified using JavaScript addPlaceholder API as shown below.

 

 

  <script type="text/javascript">

  function displayServerDocumentInViewer() {

 

      var uriField = document.getElementById("hidden_document_field_uri");

      if (uriField != null) {

          // Load the server-side document through its URI using the client-side "documentViewer" object

           documentViewer.loadDocument(uriField.value);

 

          // Create and add signature placeholder

          var signPlaceholder = {

               id: "my_sign1",

               required: false,

               pageNumber: 1,

               position: {

                   mode: gnostice.SignaturePositionMode.pageAbsolute,

                   absolutePosition: { x: 150, y: 400 }

               },

               size: { width: 150, height: 60 },

               allowUserResizing: true,

               style: { color: "blue", width: gnostice.StrokeWidth.Medium },

               includeSignerName: true,

               includeDateTime: true,

           };

           documentViewer.Signatures.addPlaceholder(signPlaceholder);

       }

 

   }

  </script>

 

 

There are several properties that can be applied when creating a placeholder to customize its appearance and behavior. Given below is a description of the properties.

 

Property

Description

id

A string identifier for each signature placeholder added to the document. This is made available on the server-side for reference so it should be unique for each placeholder added to the document.

required

A Boolean that specifies whether the user has to sign in the placeholder before the document is allowed to be saved.

pageNumber

The number of the page on which the placeholder must be placed.

position

The position of the placeholder on the specified page. The position can be specified using two modes (pageAbsolute or pageRelative).

The pageAbsolute mode allows the position to be specified as an absolute point with respect to the page top-left corner. The absolutePosition property is used to specify the coordinates of the point. An example is shown below.

 

position: {

    mode: gnostice.SignaturePositionMode.pageAbsolute,

    absolutePosition: { x: 150, y: 400 }

}

 

The pageRelative mode allows the position to be specified as a relative offset from one of the specified anchors. An example is shown below where the position is set relative to the page's bottomLeft corner. The supported anchors are: topLeft, topCenter, topRight, bottomLeft, bottomCenter, and bottomRight.

 

position: {

   mode: gnostice.SignaturePositionMode.pageRelative,

   relativePosition: {

       anchor: gnostice.SignaturePositionAnchor.bottomLeft,

       offset: { x: 150, y: 400 }

   }

}

 

size

The size of the signature placeholder rectangle specified as width and height.

allowUserResizing

A Boolean that specified whether the user is allowed to change the size the placeholder.

style

The styling of the signature stroke. The color and the width of the stroke can be specified. The supported widths are Thin, Medium, and Thick.

includeSignerName

A Boolean that specifies whether a typed name is included below the signature.

includeDateTime

A Boolean that specifies whether a date-time stamp is included below the signature. This date-time stamp is added to the PDF and is not shown on the viewer when the signature is placed.

 

The screen-shot below of the viewer shows the signature placeholder that we created earlier.

 

PDFSign_placeholder

 

Saving user signatures

The user can be allowed to save the signatures they create. The saved signatures can be used by the same user in the future for signing documents without having to recreate them. User created signatures can be accessed via the AfterDocumentSave event on the server. This event is called after the user saves the document. The handler for this event can store the signatures in a file or database and supply them back to the document viewer via the NeedUserSignatures event. An example of this is shown in the code snippet below. For the sake of brevity the example stores the signatures in the session cache.

 

 

  using Gnostice.Controls.ASP;
 

  public override void AfterDocumentSave(AfterDocumentSaveEventArgs documentSaveEventArgs)
  {
      // Create a list of the user signatures
      var signatures = new List<MySignatureKeyValPair>();
      foreach (UserSignature userSignature in documentSaveEventArgs.UserSignatures)
      {
          var sign = new MySignatureKeyValPair
          {
              Id = userSignature.SignId,
              Name = userSignature.Name,
              SignatureImage = userSignature.ImageAsBase64String
          };
          signatures.Add(sign);
      }
 
      if (signatures.Count > 0)
      {
          // Serialize the signature list to JSON
          var builder = new StringBuilder();
          using (var stringWriter = new StringWriter(builder))
          using (var writer = new JsonTextWriter(stringWriter))
          {
              var scriptSerializer = JsonSerializer.Create(new JsonSerializerSettings());
              scriptSerializer.Serialize(writer, signatures);
          }
 
          // Store the JSON in the session cache
          documentSaveEventArgs.HttpContext.Session["mySignatures"] = builder.ToString();
      }
  }
 
  public override void NeedUserSignatures(NeedUserSignaturesEventArgs needUserSignaturesEventArgs)
  {
      // Check if the session contains signatures stored earlier
      if (needUserSignaturesEventArgs.HttpContext.Session["mySignatures"] != null)
      {
          // Deserialize the JSON to a list of signature objects
          string mySignatures = needUserSignaturesEventArgs.HttpContext.Session["mySignatures"].ToString();
          var signatures = JsonConvert.DeserializeObject<List<MySignatureKeyValPair>>(mySignatures);
          foreach (var sign in signatures)
          {
              using (var memStream = new MemoryStream(Convert.FromBase64String(sign.SignatureImage)))
              {
                  var signature = new UserSignature(sign.Id, sign.Name, memStream);
                  needUserSignaturesEventArgs.UserSignatures.Add(signature);
              }
          }
      }
  }