Reputation: 35
I have a project (Windows Forms Application) which is using LinqToSql to connect to the database. Connection string for it (including password) is stored in app.config file.
This program is used by a bunch of people from my work so I thought about security and decided to encrypt connection string.
I have read some articles about this problem and figured out that there is a built-in way to secure some sections in configuration file. I even found few examples of using this tool (like this: Encrypt Connection Strings when using Linq To SQL ).
But I still have questions: 1. Where exactly in program I have to call these methods?
In my solution's data tier there are many places like this:
using(var db = new myDbDataContext())
{
//some code
}
Does this mean that I must call these encrypt/decrypt methods any time I try to get something from database? Or this code must be included in program.cs file? Or in dbml file?
Also about renaming app.config to web.config in case of using this encryption tool. I've seen this recommendation few times. Is this true that I need to do it?
How encryption is going to work on different workstations? Does it need any additional changes to code?
Upvotes: 0
Views: 937
Reputation: 1977
please have a look it will help you.
public class TestContext : DbContext
{
// this is wt we use in application we can delete default ctor it is not required
public TestContext(string connectionName)
{
// i m reading a already encrypted connection string from config
// decrpt it and set the connction of db context
var conn = ConfigurationManager.ConnectionStrings["EncryptedConnection"].ConnectionString;
this.Database.Connection.ConnectionString = Encrypt.DecryptString(conn, "myKey");
}
public virtual DbSet<Contact> Contacts { get; set; }
}
config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="EncryptedConnection" connectionString="qIhXH2MDWohYjOPJ3BiA7A4E70kRjRW3aSOMixpASFHu1oyak2YEMO3BTaRr3s5eVtuvi5dY07vK+PUm1xFZ6D1XT/qJjDvrs1SpbTHe45g=" providerName="System.Data.SqlClient" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
--- use in appplication
static void Main(string[] args)
{
// here I am using first takes a valid connectionstring from encrypt it.
// this is needed because I am showing it in console application idealy this step is independent of this
// this needs to be done by some build and deployment tool which wil copy this encrypted string to app.config
var encryptString = Encrypt.EncryptString("Data Source=yashssd;Initial Catalog=StackOverFlow1;Integrated Security=True", "myKey");
// this encryped connecton string I will save to th app.config manauly but this can be auutomated with build/ deployment tools
//var decrypt = Encrypt.DecryptString(encryptString, "myKey");
using (var ctx = new TestContext("EncryptedConnection"))
{
// for testing to see al working
//this is important to read the entity first .
var contact = ctx.Contacts.FirstOrDefault(x => x.ContactID == 1);
}
Console.ReadLine();
}
Final-- the logic of encryption / decryption // this can be a seprate application whosw function is to provide encrypted keys to diffrent application I just took one whichI foundon internet this can be changed or can bemake more secure based on user needs .
public static class Encrypt
{
// This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be
// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array.
private const string initVector = "pemgail9uzpgzl88";
// This constant is used to determine the keysize of the encryption algorithm
private const int keysize = 256;
//Encrypt
public static string EncryptString(string plainText, string passPhrase)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
//Decrypt
public static string DecryptString(string cipherText, string passPhrase)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
Upvotes: 1