Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • How do I read app.config values
  • How to do it in ASP.NET Reference: this SO question.
  • How do I store a connection string (unencrypted thus unsafe)

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?

like image 581
MarioDS Avatar asked May 15 '12 18:05

MarioDS


People also ask

How do I secure my connection string information?

The best way to secure the database connection string is to encrypt the value within the configuration file. The application would then load the encrypted value from the config file, decrypt the value, and then use the decrypted value as the connection string to connect to the database.

Where should you store the connection string information?

Connection strings in configuration files are typically stored inside the <connectionStrings> element in the app. config for a Windows application, or the web. config file for an ASP.NET application.

Is it safe to store connection string in web config?

The connection strings are mostly stored in web. config. It means that connection specific information such as database name, username, and password are stored as a clear text in a file. This is definitely a security concern for your Production servers.


1 Answers

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.

like image 163
Steven Doggart Avatar answered Sep 23 '22 03:09

Steven Doggart