【问题标题】:How to securely store a connection string in a WinForms application?如何在 WinForms 应用程序中安全地存储连接字符串?
【发布时间】:2012-05-15 18:42:49
【问题描述】:

我需要知道在 VB.NET 中为 WinForms 应用程序存储 SQL 服务器连接字符串的常用方法是什么。

我在网上搜索了以下每个问题的答案:

  • 如何读取 app.config 值
  • 如何在 ASP.NET 中实现 参考:this SO question.
  • 如何存储连接字符串(未加密因此不安全)

我想要一个完整的答案,关于如何在 VB.NET 中安全地存储连接字符串 app.config(或 settings.settings,如果更好的话)。

app.config 是正确的地方吗?我可以加密这些值吗?

【问题讨论】:

    标签: .net vb.net security encryption connection-string


    【解决方案1】:

    简单地说,.net 框架允许您这样做,请参阅

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

    相关信息:

    这进入 ma​​chine.config 文件:

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

    这是应用程序代码:

    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
    

    更新 1

    感谢@wpcoder,感谢this link

    【讨论】:

    • 由于这个问题获得了相当多的关注,我编辑了您的答案,以确保在链接断开时信息不会丢失。
    • @pylover 这回答了问题,但没有提供适当的解决方案。来自提供的 MS 链接; 注释说:The connection string can only be decrypted on the computer on which it was encrypted。 updated MS link for the article could provide the solution
    【解决方案2】:

    在我的工作中,我们将完整的连接字符串存储在 app.config 中,但我们使用 AES256 对其进行加密。它工作得很好,并增加了相当多的安全性。我们编写了一个小工具,可让您加密和解密连接字符串,因此编辑 app.config 文件非常容易。我们只是在应用程序中硬编码了加密密钥,所以如果有人想反编译程序集,他们可以弄清楚,但它提高了足够高的标准来满足我们的需求。这是我们用来加密和解密连接字符串的类:

    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
    

    实际上,我们将其封装在 ConnectionStringEncrpyter 类中,该类对密钥进行硬编码。

    【讨论】:

    • 听起来不错,但你能告诉我如何编码吗?我有一个仅用于密码的加密类,而不是整个连接字符串(开销方面)
    • @MarioDeSchaepmeester 我添加了一些示例代码。我明白——加密可能很痛苦。我们将其编码为 base64,因此它可以很好地存储在文本文件中。
    • 感谢您的帮助,但我认为 pylover 为我提供了我正在寻找的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 2020-08-08
    • 2013-06-08
    • 2011-03-14
    • 2011-10-29
    • 1970-01-01
    • 2017-02-02
    相关资源
    最近更新 更多