【问题标题】:Securely Storing Database Password安全存储数据库密码
【发布时间】:2014-09-09 22:50:34
【问题描述】:

我想在创建 SQL Server CE 数据库时为其随机生成一个加密密钥和密码,然后以某种安全方式保存该密钥,以允许程序打开连接,但不能通过以下方式轻松访问潜在的攻击者。

我正在开发一个离线 WPF 应用程序,它将某些用户和设置信息存储在本地数据库中。

我当前的实现是拥有一个用户设置的“设备密码”,用作生成的 SQL Server CE 数据库密码的加密密钥。然后将 base64 加密的数据库密码保存在一个简单的 .txt 设置文件中。当应用程序启动时,用户输入设备密码,该字符串用作保存密码的解密密钥。如果生成的字符串能够打开与数据库的连接,则密码正确并且程序以完全访问权限打开。

我现在要做的是修改系统以允许具有特定用户名/密码凭据的多个用户打开程序并以不同级别的权限访问数据库。我试图实现这一点的方法是分别处理用户身份验证,并打开数据库而不考虑凭据以加载一些基本的应用程序信息。

下面大致是我目前的实现:

        var candidateDBPwd = DecryptDatabasePassword(passwordBox.Password, Settings.Instance.EncryptedDatabasePassword);

        if (candidateDBPwd.IsNullOrEmpty())
        {
            // User's password didn't decrypt database password.
            return false;
        }

        if (File.Exists(Constants.DB_FILE))
        {
            // Normal operation: Try to open the database file to see that 
            // we've got the correct password.
            string databaseArguments = Constants.DB_ARGS_SECURE + candidateDBPwd;
            using (var conn = new SqlCeConnection(databaseArguments))
            {
                try
                {
                    conn.Open();
                }
                catch (System.Data.SqlServerCe.SqlCeException ex)
                {
                    // Failed to open the database: User's password must have been wrong!
                    return false;
                }
            }

过去几个小时我一直在研究类似的问题,现在我开始怀疑这是否可能。共识似乎表明在 App.config 文件中存储密码或连接字符串是徒劳的,因为如果您加密这些部分,您仍然需要将该密钥存储在代码中的某个位置。大多数关于这个问题的现有 SO 线程似乎已经过时了几年,而且这种做法似乎已经过时了。是否有一些新的可敬的方式来存储本地数据库密码?或者您会推荐一种不同的方法来实现该功能吗?

【问题讨论】:

  • 我读过并参考的一些类似主题如下:DatedDated but providing good context
  • 移动开发手册有几章专门讨论这个不平凡的问题:amazon.com/Microsoft%C2%AE-Mobile-Development-Handbook-Wigley/…
  • 这取决于您发布应用程序的方式。 App.config 可能会在您的应用程序首次启动期间被加密,因此您可能只需要四个。
  • @ErikEJ 感谢您的推荐,我可能需要给自己找一份副本。这本手册是在 2007 年出版的,基于 .NET 2.0。我是否应该认为这意味着从那时起就没有很多与该问题相关的实质性进展?
  • @VDohnal 我不是构建安装程序或从事发布工作的人,但我可以与他们谈谈我们的流程。有没有一种方法可以在安装过程中加密App.config,以便在程序需要重建数据库时再次访问加密密钥?

标签: c# sql-server security encryption sql-server-ce


【解决方案1】:

这里的信息是代码 sn-p,可用于加密 app.config 的某些部分。这是特定于机器的加密,我认为这是最简单直接的方法。

我将它与 Click-once 应用程序一起使用,以便在应用程序首次启动期间对配置部分进行加密。这意味着,它在发布服务器上未加密,下载时也未加密,并且在安装完成并启动应用程序后立即加密。

因此,使用这种方法,您必须分发未加密的文件,并且只有在安装完成后才会对它们进行加密。我想这可以通过在安装期间运行此代码来实现,这取决于您计划如何安装您的应用程序。

您也可以使用UnprotectSection() 对之前加密的部分进行解密。

static void EncryptConfig()
{
    // Encrypt config for ClickOnce deploys on first run
    // ClickOnce deploys config into 2 dirs, so the parent dir is traversed to encrypt all
    if (ApplicationDeployment.IsNetworkDeployed)
    {
        // Get paths
        Assembly asm = Assembly.GetExecutingAssembly();
        string exeName = Path.GetFileName(asm.Location);
        string configName = exeName + ".config";
        DirectoryInfo parentPath = Directory.GetParent(Directory.GetCurrentDirectory());

        // Protect config files
        foreach (DirectoryInfo dir in parentPath.GetDirectories())
        {
            foreach (FileInfo fil in dir.GetFiles())
            {
                if (fil.Name == configName)
                {
                    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                    fileMap.ExeConfigFilename = fil.FullName;
                    Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                    ProtectSection(config, "connectionStrings");
                    config.Save(ConfigurationSaveMode.Modified);
                }
            }
        }
    }
}
private static void ProtectSection(Configuration config, string sectionName)
{
    ConfigurationSection section = config.GetSection(sectionName);
    if (section != null)
    {
        if (!section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
        }
        section.SectionInformation.ForceSave = true;
    }
    else
        Tools.LogWarning("Section {1} not found in {0}.",config.FilePath, sectionName);
}

【讨论】:

  • 非常感谢您的回复!对此稍作修改的版本使我能够阅读和更新信息,而无需将其存储为纯文本,从而可以完全完成我一直在尝试做的事情。对于那些可能像我开始搜索时那样没有此过程经验的人,Here's a good example 一种在 App.config 中访问和保存信息的方法。
【解决方案2】:

您可以将其存储在注册表编辑器中。您提到您的系统是离线 wpf 应用程序。

【讨论】:

  • 这不是我所说的安全。
猜你喜欢
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
相关资源
最近更新 更多