0

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?

  1. 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?

  2. How encryption is going to work on different workstations? Does it need any additional changes to code?

10
  • so in this case you can create a static class which have a method which will return you the DBContext object and this method will be responsible for decrypting the connection string . Commented Jan 28, 2017 at 9:38
  • You can also read about UnitOFWork and Repository patterns which tell you how to decouple all DB related things from application and bussiness layer Commented Jan 28, 2017 at 9:39
  • asp.net/mvc/overview/older-versions/… Commented Jan 28, 2017 at 9:43
  • Thanks, I'm already using this pattern. I'll try to use your advice about method that returns DataContext. So I still have one question: link that I have posted above tells about two methods: Encrypt and Decrypt. But if these methods work during executions of programs, does it mean that before start - app.config file is unsafe? Commented Jan 28, 2017 at 10:21
  • well your app.config will always have encrypted connection string which without a key is safe . so the idea is to decrypt the string and put it in config and when app loads or when you want to connect to db you can go and read this ans decry pt it. Commented Jan 28, 2017 at 11:12

1 Answer 1

1

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);
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.