安全存储数据库密码

时间:2014-09-09 22:50:34

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

我想在创建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文件中存储密码或connectionStrings是徒劳的,因为如果加密这些部分,您仍然需要将该密钥存储在代码中的某个位置。关于这个问题的大多数现有的SO线程似乎都已经过时了几年,似乎这种做法已被弃用。是否有一些新的可敬的方式来存储本地数据库密码?或者您会推荐一种不同的方法来实现该功能吗?

2 个答案:

答案 0 :(得分:2)

此处的信息是可用于加密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);
}

答案 1 :(得分:-1)

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

相关问题