Secure InfoPath forms in SharePoint using encryption

Applies to: InfoPath 2007

Learn how you can encrypt InfoPath forms and decrypt them again to protect and secure InfoPath forms in SharePoint.

ADVERTISEMENTS

Problem

You've got an InfoPath browser form in SharePoint in which sensitive information such as personal information or credit card numbers are stored.

You want to be able to secure and restrict the viewing of this information only to people who have been authorized to view protected sensitive data in an InfoPath browser form within SharePoint (demo video).

Solution

You can use encryption to encrypt and decrypt sensitive data to secure InfoPath forms in SharePoint.

Before you begin

This article assumes that you have already mastered the InfoPath basics, know how to add conditional formatting to InfoPath controls, and know how to write code in InfoPath.

Discussion

InfoPath forms are self-contained, meaning that the InfoPath data is stored within the form itself and not in an external data store such as a database. When dealing with SharePoint, the XML of InfoPath forms is eventually stored in a SharePoint content database, but still each InfoPath form remains an XML file that contains all of its own data.

Because InfoPath forms store their own data, you need to come up with a clever way to decrypt and encrypt InfoPath form data when the form is opened and closed.

The trick to encrypting InfoPath forms to protect and secure InfoPath forms in SharePoint is to encrypt the data and empty all of the fields that contain sensitive data before the form is saved. And then when the form is opened, decrypt the data and populate the fields again with the sensitive data.

You can encrypt InfoPath forms to secure InfoPath forms in SharePoint as follows:

  1. In InfoPath, create a browser-compatible form template that resembles the following figure.

    Browser-compatible InfoPath form template with security features
    Figure 1. Browser-compatible InfoPath form template with security features.

  2. The Main data source of the InfoPath form template should resemble the following figure.

    Main data source of the secure InfoPath form template
    Figure 2. Main data source of the secure InfoPath form template.

    Description of the purpose of each node in the main data source of the secure InfoPath form template:

    • The password node is used for the user to enter a password. This field is always cleared after the user presses the Protect or Unprotect button to prevent the password from being stored in the form when the form is saved.
    • The isLocked node is used to keep track of whether the data in the InfoPath form is secured or not. This is a hidden field in the InfoPath form and is used to enable/disable the Protect and Unprotect buttons through conditional formatting.
    • The encryptedData node is used for storing the encrypted data of all of the protected fields. This is also a hidden field.
    • The emptyProtectedFields node is used to store the XML structure of all of the fields under the protectedFields group node. This data will be used to quickly empty all of the protected fields. This field is also a hidden field.
    • The protectedFields group node contains the fields that are shown on the InfoPath form and that should be secured.
    • The errorMessage node is used for displaying messages to the user. An Expression Box is used to display this field on the InfoPath form.


  3. Add the following Conditional Formatting to the Protect button:

    If this condition is true:

    isLocked is not blank

    Then apply this formatting:

    Disable this control

  4. Add the following Conditional Formatting to the Unprotect button:

    If this condition is true:

    isLocked is blank

    Then apply this formatting:

    Disable this control

  5. Add the following using statements to the InfoPath form code file:

    using System.Text;
    using System.IO;
    using System.Security.Cryptography;

  6. Add the following code to the Loading event handler of the InfoPath form template:

    try
    {
    XPathNavigator root = MainDataSource.CreateNavigator();

    // Copy the XML structure for the protectedFields node with empty values
    string emptyProtectedFields = root.SelectSingleNode(
    "/my:myFields/my:protectedFields", NamespaceManager).OuterXml;

    // Store the XML structure in the emptyProtectedFields node
    root.SelectSingleNode("/my:myFields/my:emptyProtectedFields",
    NamespaceManager).SetValue(emptyProtectedFields);
    }
    catch (Exception ex)
    {
    SetErrorMessage(ex.Message);
    }

  7. Add the following code to the Clicked event handler of the Protect button:

    try
    {
    ClearErrorMessage();

    XPathNavigator root = MainDataSource.CreateNavigator();

    // Generate the encryption key using the password
    string password = root.SelectSingleNode(
    "/my:myFields/my:password", NamespaceManager).Value;
    SymmetricAlgorithm symmKey = GenerateKey(password);

    // Retrieve and encrypt the sensitive fields
    string dataToEncrypt = root.SelectSingleNode(
    "/my:myFields/my:protectedFields", NamespaceManager).OuterXml;
    root.SelectSingleNode("/my:myFields/my:encryptedData",
    NamespaceManager).SetValue(EncryptField(symmKey, dataToEncrypt));

    // Encrypt the isLocked field
    root.SelectSingleNode("/my:myFields/my:isLocked",
    NamespaceManager).SetValue(EncryptField(symmKey, "locked"));

    // Do not save the password; empty the password field
    root.SelectSingleNode("/my:myFields/my:password",
    NamespaceManager).SetValue(String.Empty);

    // Empty the protected fields node
    string emptyProtectedFields = root.SelectSingleNode(
    "/my:myFields/my:emptyProtectedFields", NamespaceManager).Value;

    XPathNavigator container = root.SelectSingleNode(
    "//my:protectedFields", NamespaceManager);
    container.ReplaceSelf(emptyProtectedFields);
    }
    catch (Exception ex)
    {
    SetErrorMessage(ex.Message);
    }

  8. Add the following code to the Clicked event handler of the Unprotect button:

    try
    {
    ClearErrorMessage();

    XPathNavigator root = MainDataSource.CreateNavigator();

    // Retrieve the password entered by the user and generate a key
    string password = root.SelectSingleNode("/my:myFields/my:password",
    NamespaceManager).Value;
    SymmetricAlgorithm symmKey = GenerateKey(password);

    // Retrieve the encrypted data
    string encryptedData = root.SelectSingleNode(
    "/my:myFields/my:encryptedData", NamespaceManager).Value;

    // Try to decrypt the data
    string decryptedData = DecryptField(symmKey, encryptedData);

    // Put the decrypted data in the protectedFields node
    XPathNavigator container = root.SelectSingleNode(
    "//my:protectedFields", NamespaceManager);
    container.ReplaceSelf(decryptedData);

    // Empty the isLocked and password fields
    root.SelectSingleNode("/my:myFields/my:isLocked",
    NamespaceManager).SetValue(String.Empty);
    root.SelectSingleNode("/my:myFields/my:password",
    NamespaceManager).SetValue(String.Empty);
    }
    catch (CryptographicException)
    {
    string msg = "Either the password you entered is incorrect ";
    msg += "or you are not authorized to view the protected data.";
    SetErrorMessage(msg);
    }
    catch (Exception)
    {
    string msg = "The InfoPath form has been tampered with; ";
    msg += "cannot unprotect the data.";
    SetErrorMessage(msg);
    }

  9. Save the InfoPath form template and build the project.
  10. Deploy the InfoPath form template with C# code to SharePoint using an administrator-approved deployment.

You should now have a fully functional InfoPath form that displays the behavior shown in this Password-protect InfoPath browser forms in SharePoint demo video.

Note: The solution described in this article prevents everybody who is not the first person who clicks on the Protect button to secure the InfoPath form from viewing the sensitive data contained within the form. If you want to authorize a select group of people to view the secure data, you can make use of a saltValue that is an empty string (or a string that does not change) instead of the user name of the person who protects the form, and then share this password among the members of the group.

 


Related InfoPath Articles:

 

Copyright: This article may not be used on web sites (whether personal or otherwise), copied, disseminated, altered, printed, published, broadcasted, or reproduced in any way without an expressed written consent. The techniques demonstrated in this article may be used within any Microsoft InfoPath project. This article is provided without any warranties. Copyright for this article is non-transferrable and remains with the author.

InfoPath 2013 Cookbook: 121 Codeless Recipes for Beginners

InfoPath 2013 Cookbook 2: 121 Codeless Recipes for SharePoint 2013

InfoPath 2010 Cookbook: 101 Codeless Recipes for Beginners

InfoPath 2010 Cookbook 2: 101 Codeless Recipes for SharePoint 2010

InfoPath 2010 Cookbook 3: 101 Code Recipes for C# Developers

InfoPath 2010 Cookbook 4: 101 Code Recipes for VB Developers

InfoPath 2010 Cookbook 5: Integrating InfoPath with Excel and Excel Services