Web applications often need to store security-sensitive data, such as database connection strings and service account credentials in application configuration files. For security reasons, this type of information should never is stored in plain text and should always be encrypted prior to storage.
This How To describes how to use DPAPI from ASP.NET. This includes ASP.NET Web applications, Web services, and .NET Remoting components that are hosted in ASP.NET.
The code in this How To references DPAPI through a managed class library, the creation of which is described in "Appendix " in the Reference section of this book.
DPAPI can work with either the machine store or user store (which requires a loaded user profile). DPAPI defaults to the user store, although you can specify that the machine store be used by passing the CRYPTPROTECT_LOCAL_MACHINE flag to the DPAPI functions.
The user profile approach affords an additional layer of security because it limits who can access the secret. Only the user who encrypts the data can decrypt the data. However, use of the user profile requires additional development effort when DPAPI is used from an ASP.NET Web application because you need to take explicit steps to load and unload a user profile (ASP.NET does not automatically load a user profile).
The machine store approach (adopted in this How To) is easier to develop because it does not require user profile management. However, unless an additional entropy parameter is used, it is less secure because any user on the computer can decrypt data. (Entropy is a random value designed to make deciphering the secret more difficult.) The problem with using an additional entropy parameter is that this must be securely stored by the application, which presents another key management issue.
For a related article that shows how to use DPAPI with the user store from an ASP.NET Web application (by using a serviced component within an Enterprise Services application), see "Appendix " within the Reference section of this book.
The following items describe the recommended hardware, software, network infrastructure, skills and knowledge, and service packs you will need.
Microsoft® Windows® 2000 operating system
Microsoft Visual Studio® .NET development system
The procedures in this How To also require that you have knowledge of building ASP.NET Web applications with Microsoft Visual C#™ development tool.
Before working through this How To, you must perform the steps described in "Appendix " in order to create the DPAPI managed class library used by code in this How To.
This How To includes the following steps:
This procedure creates an ASP.NET client Web application that will call the DPAPI class library to encrypt and decrypt data stored within the Web.config file.
▸ To create an ASP.NET client Web application
Start Visual Studio .NET and create a new C# ASP.NET Web application called DPAPIClientWeb.
Add a reference to the DataProtector.dll assembly, previously created in "Appendix ."
Open WebForm1.aspx.cs and add the following using statements to the top of the file beneath the existing using statements.
using System.Text; using DataProtection;
Add the controls listed in Table 1 to WebForm1.aspx.
Table 1. WebForm1.aspx controls
Control Type | Text | ID |
---|---|---|
Button | Encrypt | btnEncrypt |
Button | Decrypt | btnDecrypt |
TextBox | txtDataToEncrypt | |
TextBox | txtEncryptedData | |
TextBox | txtDecryptedData | |
Label | lblError | |
Label | Data To Encrypt | |
Label | Encrypted Data | |
Label | Decrypted Data |
Your Web form should look similar to Figure 1.
Double-click the Encrypt button to create a button click event handler.
DataProtector dp = new DataProtector( DataProtector.Store.USE_MACHINE_STORE ); try { byte[] dataToEncrypt = Encoding.ASCII.GetBytes(txtDataToEncrypt.Text); // Not passing optional entropy in this example // Could pass random value (stored by the application) for added security // when using DPAPI with the machine store. txtEncryptedData.Text = Convert.ToBase64String(dp.Encrypt(dataToEncrypt,null)); } catch(Exception ex) { lblError.ForeColor = Color.Red; lblError.Text = "Exception.<br>" + ex.Message; return; } lblError.Text = "";
Return to the Web form and double-click the Decrypt button. Add the following code to the button click event handler.
DataProtector dp = new DataProtector(DataProtector.Store.USE_MACHINE_STORE); try { byte[] dataToDecrypt = Convert.FromBase64String(txtEncryptedData.Text); // Optional entropy parameter is null. // If entropy was used within the Encrypt method, the same entropy parameter // must be supplied here txtDecryptedData.Text = Encoding.ASCII.GetString(dp.Decrypt(dataToDecrypt,null)); } catch(Exception ex) { lblError.ForeColor = Color.Red; lblError.Text = "Exception.<br>" + ex.Message; return; } lblError.Text = "";
On the Build menu, click Build Solution.
This procedure tests the Web application to confirm that data is successfully encrypted and decrypted.
▸ To test the application
Press Ctrl+F5 to run the Web application.
Enter a string in the Data to Encrypt text box and click Encrypt.
Confirm that encrypted data (in Base64 encoded format) is displayed in the Encrypted Data text box.
Click the Decrypt button.
Confirm that the encrypted data is successfully decrypted and displayed in the Decrypted Data text box.
This procedure takes an encrypted database connection string and places the encrypted cipher text into the application’s Web.config file within an <appSettings> element. You will then add code to read and decrypt this string from the configuration file.
▸ To modify the Web application to read an encrypted connection string from Web.config
Return to Visual Studio .NET and display the WebForm1.aspx in Designer mode.
Add another button to the form. Set its Text property to Decrypt string from config file and its ID property to btnDecryptConfig.
Double-click the button to create a button click event handler.
Add the following using statement to the top of the file beneath the existing using statements.
using System.Configuration;
Return to the btnDecryptConfig_Click event handler and add the following code to retrieve a database connection string from the <appSettings> section of the Web.config file.
DataProtector dp = new DataProtector(DataProtector.Store.USE_MACHINE_STORE); try { string appSettingValue = ConfigurationSettings.AppSettings["connectionString"]; byte[] dataToDecrypt = Convert.FromBase64String(appSettingValue); string connStr = Encoding.ASCII.GetString( dp.Decrypt(dataToDecrypt,null)); txtDecryptedData.Text = connStr; } catch(Exception ex) { lblError.ForeColor = Color.Red; lblError.Text = "Exception.<br>" + ex.Message; return; } lblError.Text = "";
On the Build menu, click Build Solution to rebuild the projects.
Right-click WebForm1.aspx, and then click View in Browser.
Enter a database connection string such as the one that follows into the Data to Encrypt field.
server=(local);Integrated Security=SSPI; database=Northwind
Click the Encrypt button.
Select the encrypted cipher text and copy it to the clipboard.
Switch to Visual Studio .NET, open Web.config and add the following <appSettings> element outside of the <system.web> element. Assign the encrypted connection string currently on the clipboard to the value attribute.
<appSettings>
<add key="connectionString" value="encrypted connection string"/>
</appSettings>
Save Web.config.
Click the Decrypt string from config file button and confirm that the encrypted database connection string is successfully read from the Web.config file and that the decrypted connection string is successfully displayed in the Decrypted data field.