12

我有一个困扰我多年的场景。如果您必须使用用户名和密码连接到数据库或其他服务(如 Web 服务),如果您通过 .NET 程序集进行连接,那么在哪里存储这些信息最安全?我知道您必须对密码进行加密,但是您会遇到一种先有鸡还是先有蛋的问题——很好——您可以对其进行加密,但是您将密钥放在哪里?

在 .NET 中,您不能对密码进行硬编码,因为您可以反编译 .NET 代码。

我研究了在隔离存储中使用基于程序集的权限,但 MS 建议不要在其中存储未加密的秘密项目,因为特权用户可以获得访问权限,所以我们再次将问题从 A 点转移到 B 点。例如,域管理员由于能够成为域上任何工作站的管理员,因此无需了解数据库中的信息就可以访问。

您可以加密应用程序。Config 和 Web.Config,但我相信特权用户可以访问密钥。

我认为您在使用 DPAPI 时遇到了同样的问题。

我曾考虑将密码存储在远程数据库中,并通过操作系统身份验证获取它们,但我们部门禁止将密码存储在数据库服务器上。我很确定我被卡住了,想要确认。

4

5 回答 5

11

您不想将密码存储在程序集中,重新发明轮子只会带来更多的麻烦(并引入更多的漏洞),而不是它的价值。如果您在数据库和 Web 服务器上都使用 MS 平台,那么处理此问题的最简单方法是使用受信任的连接,并将 SQL 服务器上的权限授予您的应用程序正在使用的身份。

其次,我会让 DPAPI 完成它的工作来加密你的连接设置

于 2012-03-07T22:08:35.890 回答
4

您可以使用.NET Framework的以下方法来保护您的数据;他们在内部使用DPAPI来保护您的数据,您可以直接在 C# 或 VB.NET 中使用它们,而无需摆弄系统 DLL 调用:

namespace System.Security.Cryptography
{
    // Summary:
    //     Provides methods for protecting and unprotecting data. This class cannot
    //     be inherited.
    public sealed class ProtectedData
    {
        public static byte[] Protect(byte[] userData, 
            byte[] optionalEntropy, DataProtectionScope scope);
        public static byte[] Unprotect(byte[] encryptedData, 
            byte[] optionalEntropy, DataProtectionScope scope);
    }
}

要使用它,请添加对System.Security您项目的引用。我强烈建议使用字节数组optionalEntropy向受保护的数据添加SALT(向字节数组添加一些随机值,这些值对于您要保护的数据是唯一的)。

scope可以使用DataProtectionScope.CurrentUser,它将使用当前用户的凭据加密要保护的数据。

在某些情况下,DataProtectionScope.LocalMachine也很有用。在这种情况下,受保护的数据与机器上下文相关联。使用此设置,计算机上运行的任何进程都可以取消保护数据。它通常用于在不允许不受信任的用户访问的服务器上运行的特定于服务器的应用程序中。

使用Protect方法对数据进行加密,用Unprotect. 您可以根据应用程序(文件、数据库、注册表等)的要求存储返回的字节数组。

有关这些方法的更多信息,请参见 MSDN:

对于代码示例,如果您对加密应用程序的 .config 文件的某些部分感兴趣,请查看以下内容:

我建议您使用SALT(通过使用optionalEntropy参数) - 它可以防止彩虹表攻击。


我想提一下 DPAPI 解决方案的一个缺点:密钥是根据您的 Windows 凭据生成的,这意味着有权访问您的 Windows 凭据的任何人都可能有权访问受保护的数据。在您的帐户下运行的程序也可以访问受保护的数据。

于 2013-03-11T15:19:39.960 回答
1

这是一个很好的问题,我自己一直在寻找答案。我遇到的问题是保持数据库密码的安全,以防服务器被黑客入侵并且可以检索单个文件。我发现的一个非常有趣的选项是 web.config 的部分可以通过 .NET 框架自动加密和解密,该框架将使用 Windows 安全存储为您保存和检索加密密钥。在我的情况下,由于我的托管服务提供商不支持它而无法使用,但您可以查看此选项。我认为它可能起作用的原因是,您可以独立管理用户可能访问 Windows 安全商店的安全性,并显着限制任何潜在的违规行为。

于 2012-03-08T22:02:53.883 回答
1

****已针对 Windows 10 1903+ 更新 ****

Microsoft 已从 WinMetadata 中删除了以前方法使用的 dll,即使执行旧操作,它们现在也不可用。相反,他们现在建议使用 Target Framework Moniker 或名为Microsoft.Windows.SDK.Contracts的 Nuget 包,这些包公开了现代 Windows API。[官方细节可以在这里找到]。请注意,要正确安装 nuget,必须将数据包管理设置为PackageReference而不是Packages.configelsewise,即使它看起来像已安装,但它不起作用。

如果尚未设置此管理器,通常可以通过右键单击 packages.config 文件并选择 将 packages.config 文件转换为新格式(集成在项目文件中)Migrate。如果 Packages.config 文件尚不存在,则可以通过进入 Nuget 选项将默认设置为使用 PackageReference。请注意,默认设置在 .Net FW、.Net Std 和 .Net Core 之间有所不同。当我个人不得不这样做时,奇怪的是,它不想迁移文件。我必须完全卸载我的包,删除文件,设置默认值并重新安装包。如果我没记错的话,与 TFVC 有关。

然后 API 应该再次可用。

**** 原帖 ****

如果您使用的是仅 Windows 8+的解决方案,您还可以使用 Windows 密码库。最初,它是为 Metro Apps 构建的,但也支持 Winform 和 WPF 应用程序。

基本上,你需要的是

  1. 在第一个属性组内的项目文件中添加以下行
    <TargetPlatformVersion>8.0</TargetPlatformVersion>

  2. 参考Windows.Security

    • 打开参考管理器窗口
    • 选择Windows选项卡
    • 选择Core子标签
    • 检查Windows.Security
  3. 在代码中,使用(这是 vb 但 C# 是等效的)

    Dim vault = New Windows.Security.Credentials.PasswordVault()
    vault.Add(New Windows.Security.Credentials.PasswordCredential(resource, userName, password))
    Dim cred = vault.Retrieve(resource, logon)
    cred.RetrievePassword()
    Dim pwd = cred.Password
    

参考:

  1. https://docs.microsoft.com/fr-ca/archive/blogs/cdndevs/using-windows-8-winrt-apis-in-net-desktop-applications
  2. https://docs.microsoft.com/en-us/uwp/api/Windows.Security.Credentials.PasswordVault?view=winrt-19041
于 2020-11-25T20:06:35.820 回答
0

这里有几个选项。

  1. 将它们存储在加密的配置文件中
  2. 将它们存储在使用生成的种子加密的外部文件中。混淆存储此基本种子的代码或将其存储在 c++ dll 中(难以反编译)。
于 2012-03-08T02:47:21.300 回答