C# 安全地存储数据库密码
我希望在创建SQL Server CE数据库时随机生成该数据库的加密密钥和密码,然后以某种安全的方式保存该密钥,以允许程序打开连接,但潜在攻击者不容易访问 我正在开发一个离线WPF应用程序,它将某些用户和设置信息存储在本地数据库中 我当前的实现是让用户设置一个“设备密码”,作为生成的SQL Server CE数据库密码的加密密钥。然后,base64加密数据库密码保存在一个简单的.txt设置文件中。当应用程序启动时,用户输入设备密码,该字符串用作已保存密码的解密密钥。如果生成的字符串能够打开到数据库的连接,则说明密码正确,并且程序以完全访问权限打开 我现在要做的是修改系统,允许具有特定用户名/密码凭据的多个用户以不同的权限级别打开程序并访问数据库。我试图实现这一点的方法是分别处理用户身份验证,并打开数据库而不考虑凭据以加载一些基本的应用程序信息 下面是我当前的大致实现:C# 安全地存储数据库密码,c#,sql-server,security,encryption,sql-server-ce,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文件中存储密码或连接字符串是徒劳的,因为如果加密这些部分,仍然需要将该密钥存储在代码中的某个位置。关于这个问题的大多数现有SO线程似乎已经过时了好几年,而且这种做法似乎已经过时。是否有一些新的值得尊敬的方法来存储本地数据库密码?或者您会推荐一种不同的方法来实现该功能吗?您可以将其存储在注册表编辑器中。您提到您的系统是脱机wpf应用程序。这里是可用于加密
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);
}
我已经阅读并提到的一些类似的主题如下:《移动开发手册》有几章专门讨论这个非平凡的问题:这取决于您如何发布应用程序App.config
可以在应用程序首次启动时进行加密,因此对您来说可能没什么问题。@ErikEJ谢谢您的推荐,我可能需要给自己弄一份副本。本手册于2007年出版,基于.NET2.0。我是否应该认为这意味着从那时起,与该问题相关的实质性进展就不多了?@VDohnal我不是构建安装程序或出版工作的人,但我可以向他们介绍我们的流程。是否有一种方法可以在安装过程中对App.config进行加密,以便在程序需要重建数据库时再次访问加密密钥?这并不是我所说的安全。非常感谢您的回复!一个稍加修改的版本让我能够完全按照我一直尝试的方式来阅读和更新信息,而无需将其存储在纯文本中。对于那些可能没有像我开始搜索时那样经历过这个过程的人来说,有一种方法可以在App.config中访问和保存信息。