Development World

New Development Technologies , Computer Last News , Tips & Tricks , UI , CSS , HTML , ASP , C# , .net Framework , Patterns & Practices & etc

Encryption of connection strings in .NET and official kick off for the blog

So basically i will kick off this blog for real before Joakim gets the chance. This post is about an interesting thing that enhances the security when working with connection strings.
When working against databases it is inevitable to use connection strings from config file. There is a way of encrypting these in an easy way using a command:
aspnet_regiis -pe "connectionStrings" -app "/myWebsite" -prov "provider"
This is pretty easy and straight forward. However, sometimes you wan't to be able to do this programatically. It can sometimes be nice to have an app that encrypts and decrypts the strings. so you don't need to bother with commands. I have chosen to show how to do this when you have you're custom provider configuration directly in the config file that holds the connection strings (the stuff that says what type of encryption you want to use and how, for more information on what you can choos please refer to MSDN). You can however use the configuration from machine.config as well. So if we start with looking at the configuration of the provider:

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
   <
providers>
      <add name="RsaProtectedConfigurationProvider2"
     
type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0,
      
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to
      encrypt and decrypt
" keyContainerName="NetFrameworkConfigurationKey" cspProviderName=""
     
useMachineContainer="false" useOAEP="false" />
   </providers>
</
configProtectedData>


I will not go into details on what each attribute in the add element sets. The important attribute for this article is useMachineContainer.This attribute declare whether to encrypt the strings for the specific machine or, if set to false, for the specific user executing the encryption. .NET creates a key bound to either the machine or the user that later on will be used to decrypt or encrypt the strings. This way only that specific machine or user can use the connectionstrings.
Of course, this implies that your application only uses one machine or user to access the database.
Now that we have the configuration set in the config file containing the connection strings let's proceed with the actual encryption. Our actual connection strings look like this:
<connectionStrings>
<clear />
   <
add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated
  
Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
  
providerName="System.Data.SqlClient" />
</
connectionStrings>
We start with opening the actual configuration file first.
// Map to the application configuration file.
ExeConfigurationFileMap configFile= new ExeConfigurationFileMap();
// Set which file to encrypt
configFile.ExeConfigFilename = "C:\mywebpage\Web.config";
//this object is a represantion of the config-file
Configuration config= null;
//sets the actual configfile to be used, this file is located elsewhere so the
//OpenMappedExeConfiguration is used, else if the local config file is to be used
//OpenExeConfiguration should be used to set the Configuration object.
config = ConfigurationManager.OpenMappedExeconfiguration(configFile, ConfigurationUserLevel.None);

 
When this is done we need to get the section that we wan't to protect. The class Configuration has a property that gives the connectionstrings.
// Get the section to protect.
ConfigurationSection section = config.ConnectionStrings;

After that we just have to check if the section is either already encrypted or if it's locked for some reason. The we simply use the method section.SectionInformation.ProtectSection to protect the strings with the provider that we set in the config file. If a provider from machine.config is to be used simply declare that one instead.
//check if the section already is encrypted or if it's locked
if ((section.SectionInformation.IsProtected == false) && (section.ElementInformation.IsLocked == false))
{
   section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider2");
  
// Save the encrypted section
   section.SectionInformation.ForceSave = true;
   config.Save(ConfigurationSaveMode.Full);
}
Now the connection string section in the config file will look like this:
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider2">
   <
EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
     
xmlns="http://www.w3.org/2001/04/xmlenc#">
   <
EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
   <
KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <
EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
      <
EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
      <
KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
         <
KeyName>Rsa Key</KeyName>
      </
KeyInfo>
     <
CipherData><CipherValue>TnrIUTyOaOHuECtnyfq7JYrxqKonECKmY6twlXNgvxWp+
                       oIzaWOeIOxO1a/KWgkoypkIVEev1T0vJZXlHB2yybHPS8yjkh9p8
                       znBNFujJS5XT0bW3YXYhL0kSzjB8uAcxI/HJ8cl2FHEsHwDozMyp
                       DyqyqnOJuBUalEyIVinRNY=
</CipherValue>
     </CipherData>
    </
EncryptedKey>
   </
KeyInfo>

  <CipherData><CipherValue>Z5ikT6Vu5IyLvWX/+NFFChricWH3Z6WNseZgsLr4qe
            
56YlcBiJqpf2x/gFeZb3UWl7IMJVHUSCrV1BAPMsb0CgrHS
       
jHaVK7pxrkN7mHoFosJO3ojMMFttz0urELqhEVZu+QleNVGaPuLf1WEz4o
DohEjF55dVpUdQtyO/892VbIakhrBM4vQr3vXI3UZYlEmz0tfJAv2u8FCQ0QneAhD1t
+YSzobgnq4KSPZWCi7c5U9Cl959bQ+RiTTzNh5VIwu/fmWnmsTAdifVUzk1OrOljGiFYI6
3gILsKyMem479NpluROSVuROBkQl464TAdT5tXMIiFivWcZg+XOCZ0g8qp6C6TjMMw+wX
zgp2RXda64rdDzC/xTjLkknoEeOw4x7fPcdgIT4dr+NO1cCxCokq8M0ro8+U1KVk/RsHxMS
114FksPhcnl1iIvGG2J8YdWKlzCAVj+xBDoY8N+8/14iPipOsZN+inH6HU03kJvEsvvoZDFsSXCiy
YxDc+ioQ7Q6vr4r3kMpBSVLPNwXSd7daOsTgVsu2334d7p4kNSnnb1riRj5imcPXq/KR
qIbaRgGl9jIie5WDKu4P9fAybVicFxnu38G6hslIxqbFRDQufPWlq5dwrsdLGGTBaQ8cxL1zQf/
KqymNvgesxqXKXnF14sc3scLDHkYBQ6quVTiYdJUELkQ0+PY4QK3tW7kyKofWYov6Gf/
d+Ee/1JtM+VtOPLkA0xrptS+PF8V/veVprpPv2/TKC7vTGtevA0elSOByeGXg1WXdyV
4F3diCIWf3r7d1y+74myhNanpGg77v9Cp6umiN6ih5AgJbhhkJEYkjzcQczurk6O8DkiToi
NGcqpZiqVZ9VcF
</CipherValue>
  </
CipherData>
   </
EncryptedData>
</
connectionStrings>

To decrypt it simply call the method section.SectionInformation.UnprotectSection instead of section.SectionInformation.ProtectSection. Be however sure to do this using the same machine or user that encrypted the strings. Otherwise it won't work.

Basically the key here is to use same user for encrypting and decrypting. You don't have to create keys on your own or hassle with other stuff. Just make sure that you run the code from the right machine or with the right user.

I have made a small Windows application where all this is implemented. It also gives you a rather limited possibility to edit the file. The main purpose is howerver to load a config file and in that file perform the above. There doesn't seem to be a spot for uploading files so feel free to contact me if you would like the application and the source code.

 

Referene : http://www.developersingravy.com/post/2008/10/17/Encryption-of-connection-string-in-NET.aspx