Password-Protecting Sensitive InfoPath Form Fields
page 4 of 6
by S.Y.M. Wong-A-Ton
Feedback
Average Rating: 
Views (Total / Last 10 Days): 38148/ 49

Designing the InfoPath Form

We will create a credit card form with a credit card number field (ccNumber) as the sensitive field to protect, and we will add login functionality to the form.

Create a new Microsoft Office InfoPath Project within Microsoft Visual Studio .NET 2003.  When prompted to select a form template for your application, choose Create a new form template. Use the field names and data types shown in Figure 1 to construct the main data source of the form.

 

Figure 1 - Main data source of the InfoPath form

 

 

Drag the fields - except for the isLocked field - onto the form and convert them into the controls shown in Figure 2.

Figure 2 - InfoPath form in design mode

Simulating a Password Control in InfoPath

InfoPath does not come with a Password Control, so you must create your own.  Two password fields are used in this solution: password and passwordAgain (see Figures 1 and 3).  The user is required to enter the same password twice, once in the password field and once in the passwordAgain field.  You must add two validation checks on both password fields: the password fields must not be blank, and the passwords must be the same.

Password fields are usually masked with asterisks (*) for privacy reasons.  Since this functionality is not available in InfoPath, you can set the font of the password and passwordAgain fields to Webdings or Wingdings to simulate masking the passwords as they are entered.  This is the closest you will get to simulating a Password Control in InfoPath.

Figure 3 - Wingdings font used to mask text when typing in passwords

 

Enabling / Disabling the Unlock Button

The Unlock button is disabled whenever the protected field (ccNumber) has been decrypted or when the form is opened for the first time.  It is enabled whenever the form is in a protected state.

The isLocked field is used to determine whether the form contains encrypted data.  It always has one of two values: an empty string or an encrypted version of the text "locked".  If it contains an empty string, form fields are shown in clear text, in which case the Unlock button should be disabled.  If the isLocked field contains an encrypted version of the text "locked", it means that sensitive form fields are being protected, and that the Unlock button should be enabled.

Use conditional formatting to enable/disable the Unlock button by checking whether the isLocked field is blank.

Namespaces

Visual Studio adds two namespaces to the form's code by default: System and Microsoft.Office.Interop.InfoPath.SemiTrust.  Three additional namespaces are required for encryption/decryption purposes: System.Text, System.IO, and System.Security.Cryptography (see Listing 1).

Listing 1 - Additional namespaces required

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

Encryption / Decryption Methods

The two methods shown in Listings 2 and 3 are used to encrypt and decrypt data.  Both methods take two parameters: a symmetric key and the text to encrypt or decrypt.

Listing 2 - Private method to encrypt data

private string EncryptField(SymmetricAlgorithm
SymmetricKey, string
  ValueToEncrypt)
{
  string base64enc = string.Empty;
  try
  {
    byte[]dataToEncrypt =
Encoding.Unicode.GetBytes(ValueToEncrypt);
    MemoryStream ms = new MemoryStream();
 
    CryptoStream csBase64 = new CryptoStream(ms,
new ToBase64Transform(),
      CryptoStreamMode.Write);
    CryptoStream csRijndael = new
CryptoStream(csBase64,
      SymmetricKey.CreateEncryptor(), CryptoStreamMode.Write);
 
    csRijndael.Write(dataToEncrypt, 0,
(int)dataToEncrypt.Length);
    csRijndael.FlushFinalBlock();
 
    base64enc =
Encoding.ASCII.GetString(ms.GetBuffer(), 0, (int)ms.Length);
  }
  catch (Exception ex)
  {
    thisXDocument.UI.Alert("The following
error occurred: " + ex.Message);
  }
  return base64enc;
}

Listing 3 - Private method to decrypt data

private string DecryptField(SymmetricAlgorithm
SymmetricKey, string
  ValueToDecrypt)
{
  string unencryptedString = string.Empty;
  try
  {
    byte[]dataToDecrypt =
Convert.FromBase64String(ValueToDecrypt);
    MemoryStream ms = new MemoryStream();
 
    CryptoStream csRijndael = new
CryptoStream(ms, SymmetricKey.CreateDecryptor
      (), CryptoStreamMode.Write);
 
    csRijndael.Write(dataToDecrypt, 0,
(int)dataToDecrypt.Length);
    csRijndael.FlushFinalBlock();
 
    unencryptedString =
Encoding.Unicode.GetString(ms.GetBuffer(), 0, (int)
      ms.Length);
  }
  catch
(System.Security.Cryptography.CryptographicException)
  {
    string msg = "Either the password you
entered is incorrect ";
    msg += "or you are not authorized to
view protected data.";
    thisXDocument.UI.Alert(msg);
  }
  catch (Exception)
  {
    string msg = "The InfoPath form has
been tampered with; ";
    msg += "cannot unprotect data.";
    thisXDocument.UI.Alert(msg);
  }
 
  return unencryptedString;
}

The symmetric key is generated from the password entered into the form and the name of the user who is logged onto the system.  The PasswordDeriveBytes class of the System.Security.Cryptography namespace takes 4 parameters:

1.      Password

2.      Key salt

3.      Hash name

4.      Number of iterations to generate the key

This class is used to generate a key from the password.  The user name, which is automatically retrieved with System.Environment.UserName, is used as the salt for the key to ensure its uniqueness.  The private method that generates the symmetric key is shown in Listing 4.

Listing 4 - Private method to generate a symmetric key from a password and user name

private SymmetricAlgorithm GenerateKey(string
password)
{
  string saltValue =
System.Environment.UserName;
  SymmetricAlgorithm symmKey = new
RijndaelManaged();
  byte[]saltValueBytes =
Encoding.ASCII.GetBytes(saltValue);
  PasswordDeriveBytes passwordKey = new
PasswordDeriveBytes(password,
    saltValueBytes, "SHA1", 3);
  symmKey.Key =
passwordKey.GetBytes(symmKey.KeySize / 8);
  symmKey.IV =
passwordKey.GetBytes(symmKey.BlockSize / 8);
  return symmKey;
}

Event Handlers

Two event handlers are used in the form: one to handle the OnSaveRequest event for when the form is saved, and one to handle the OnClick event on the Unlock button.

The OnSaveRequest event handler contains code to encrypt data and empty the two password fields (see Listing 5).  The OnClick event handler for the button contains code to decrypt encrypted data and empty the isLocked field (see Listing 6).

Listing 5 - Code snippet from the OnSaveRequest event handler

// Encrypt the sensitive fields
thisXDocument.DOM.selectSingleNode("/my:myFields/my:isLocked").text
=
  EncryptField(symmKey, "locked");
string ccNumber =
thisXDocument.DOM.selectSingleNode("/my:myFields/my:ccNumber")
  .text;
thisXDocument.DOM.selectSingleNode("/my:myFields/my:ccNumber").text
=
  EncryptField(symmKey, ccNumber);
// Do not save the password; empty the password             
thisXDocument.DOM.selectSingleNode("/my:myFields/my:loginBox/my:password").text
  = string.Empty;
thisXDocument.DOM.selectSingleNode("/my:myFields/my:loginBox/my:passwordAgain")
  .text = string.Empty;

Listing 6 - Code snippet from the btnUnlock_OnClick event handler

// Decrypt the encrypted fields                                         
string ccNumber =
thisXDocument.DOM.selectSingleNode("/my:myFields/my:ccNumber")
  .text;
thisXDocument.DOM.selectSingleNode("/my:myFields/my:ccNumber").text
=
  DecryptField(symmKey, ccNumber);
// Empty the isLocked field so that the Unlock
button is disabled             
thisXDocument.DOM.selectSingleNode("/my:myFields/my:isLocked").text
=
  string.Empty;

View Entire Article

User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-16 11:09:53 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search