MarioDS
MarioDS

Reputation: 13063

How to securely store a connection string in a WinForms application?

I need to know what is the common way to store a SQL server connection string for a WinForms application in VB.NET.

I have searched the net and I found answers to each of the following questions:

I would like a full answer on how to store a connection string in VB.NET in app.config (or settings.settings if it's better) securely.

Is app.config the right place? Can I encrypt these values?

Upvotes: 9

Views: 26256

Answers (2)

pylover
pylover

Reputation: 8055

Simply , the .net framework allows you to do that , see

http://msdn.microsoft.com/en-us/library/89211k9b(v=vs.80).aspx

Relevant information:

This goes into the machine.config file:

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
  <providers>
    <add name="RsaProtectedConfigurationProvider" 
      type="System.Configuration.RsaProtectedConfigurationProvider, ... />
    <add name="DataProtectionConfigurationProvider" 
      type="System.Configuration.DpapiProtectedConfigurationProvider, ... />
  </providers>
</configProtectedData>

And this is the application code:

Shared Sub ToggleConfigEncryption(ByVal exeConfigName As String)
    ' Takes the executable file name without the
    ' .config extension.
    Try
        ' Open the configuration file and retrieve 
        ' the connectionStrings section.
        Dim config As Configuration = ConfigurationManager. _
            OpenExeConfiguration(exeConfigName)

        Dim section As ConnectionStringsSection = DirectCast( _
            config.GetSection("connectionStrings"), _
            ConnectionStringsSection)

        If section.SectionInformation.IsProtected Then
            ' Remove encryption.
            section.SectionInformation.UnprotectSection()
        Else
            ' Encrypt the section.
            section.SectionInformation.ProtectSection( _
              "DataProtectionConfigurationProvider") 'this is an entry in machine.config
        End If

        ' Save the current configuration.
        config.Save()

        Console.WriteLine("Protected={0}", _
        section.SectionInformation.IsProtected)

    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try
End Sub

UPDATE 1

Thanks @wpcoder, for this link

Upvotes: 11

Steven Doggart
Steven Doggart

Reputation: 43743

At my job, we store the full connection strings in the app.config, but we encrypt them with AES256. It works pretty well and adds a fair amount of security. We wrote a little tool that lets you encrypt and decrypt connection strings so editing the app.config files is pretty easy. We just have the encryption key hardcoded in the application, so if anyone cared to decompile the assemblies, the could figure it out, but it raises the bar high enough for our needs. Here's the class we use to encrypt and decrypt the connection strings:

Public Class Aes256Base64Encrypter
    Public Function Decrypt(ByVal encryptedText As String, ByVal secretKey As String) As String
        Dim plainText As String = Nothing
        Using inputStream As MemoryStream = New MemoryStream(System.Convert.FromBase64String(encryptedText))
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(inputStream, algorithm.CreateDecryptor(), CryptoStreamMode.Read)
                Dim outputBuffer(0 To CType(inputStream.Length - 1, Integer)) As Byte
                Dim readBytes As Integer = cryptoStream.Read(outputBuffer, 0, CType(inputStream.Length, Integer))
                plainText = Unicode.GetString(outputBuffer, 0, readBytes)
            End Using
        End Using
        Return plainText
    End Function


    Public Function Encrypt(ByVal plainText As String, ByVal secretKey As String) As String
        Dim encryptedPassword As String = Nothing
        Using outputStream As MemoryStream = New MemoryStream()
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(outputStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write)
                Dim inputBuffer() As Byte = Unicode.GetBytes(plainText)
                cryptoStream.Write(inputBuffer, 0, inputBuffer.Length)
                cryptoStream.FlushFinalBlock()
                encryptedPassword = System.Convert.ToBase64String(outputStream.ToArray())
            End Using
        End Using
        Return encryptedPassword
    End Function


    Private Function getAlgorithm(ByVal secretKey As String) As RijndaelManaged
        Const salt As String = "put a salt key here"
        Const keySize As Integer = 256

        Dim keyBuilder As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(secretKey, Unicode.GetBytes(salt))
        Dim algorithm As RijndaelManaged = New RijndaelManaged()
        algorithm.KeySize = keySize
        algorithm.IV = keyBuilder.GetBytes(CType(algorithm.BlockSize / 8, Integer))
        algorithm.Key = keyBuilder.GetBytes(CType(algorithm.KeySize / 8, Integer))
        algorithm.Padding = PaddingMode.PKCS7
        Return algorithm
    End Function
End Class

Actually, we wrapped that inside of a ConnectionStringEncrpyter class which hardcodes the secret key.

Upvotes: 8

Related Questions