使用Windows .NET或ASP.NET应用程序时,存储数据库密码的位置

Cyn*_*der 12 c# vb.net asp.net password-protection password-storage

我有一个困扰我多年的情景.如果必须使用用户名和密码连接到数据库或其他服务(如Web服务),那么在通过.NET程序集连接时,哪里是存储此信息的最安全的位置?我知道你必须加密密码,但是你遇到了一种鸡蛋问题 - 很好 - 你可以对它进行加密,但是你把密钥放在哪里?

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

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

您可以加密App.Config和Web.Config,但我相信用户可以访问密钥.

我认为你遇到了与DPAPI相同的问题.

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

Hac*_*ese 9

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

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


Mat*_*att 5

如果您只是想让它远离 GIT,并且不需要加密,您可以按照所述使用Secret Manager Tool 。然后它存储在secrets.json您的用户配置文件内的文件中(但未加密)。正如 Microsoft 所描述的,它仅限于 ASP.NET Core 应用程序,但事实并非如此 -另一个 StackOverflow 问答向您展示了如何在.NET Core 控制台应用程序中执行此操作。

\n

但如果你需要\xc2\xa0加密,\xc2\xa0你可以使用.NET Framework的以下方法;它们在内部使用DPAPI来保护(加密)您的数据,您可以直接在 C# 或 VB.NET 中使用它们,而无需摆弄系统 DLL 调用:

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

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

\n

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

\n

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

\n

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

\n

如果必须保护字符串,可以使用辅助方法,例如:

\n
byte[] GetBytes(string text) => System.Text.Encoding.Unicode.GetBytes(text);\n
Run Code Online (Sandbox Code Playgroud)\n

将其转换为字节数组。

\n

反之亦然,如果取消保护字节数组,则可以取回字符串:

\n
string GetString(byte[] text) => System.Text.Encoding.Unicode.GetString(text);\n
Run Code Online (Sandbox Code Playgroud)\n

如果您的字符串不是 Unicode,您可以在中找到更多编码System.Text.Encoding.NET 库中找到更多编码。

\n

简单示例(将上面的帮助器方法与 ProtectedData 类一起使用):

\n
using System.Security.Cryptography;\nusing static System.Security.Cryptography.ProtectedData;\n\nvoid Main()\n{\n    const DataProtectionScope scope = DataProtectionScope.CurrentUser;\n    byte[] salt = GetBytes("s5Dk9Fj2L12"); // change the salt\n    \n    // protect msg\n    string msg = "Hello World!";\n    var protMsg = Protect(GetBytes(msg), salt, scope);\n    \n    // get plaintext back\n    string plainTxt = GetString(Unprotect(protMsg, salt, scope));\n    Console.WriteLine(plainTxt);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有关 DPAPI 方法的更多信息,请访问 MSDN:

\n\n

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

\n\n

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

\n
\n

我想提一下 DPAPI 解决方案的一个缺点:密钥是根据您的 Windows 凭据生成的,这意味着任何有权访问您的 Windows 凭据的人都可能有权访问受保护的数据(但请注意,情况也是如此)如果您使用BitLocker来加密您的文件)。在您的帐户下运行的程序也可以访问受保护的数据。

\n
\n

最后一点评论:您可以结合此处描述的技术(即使用 Secret Manager Tool 并加密文件中存储的设置secret.json- 但是您需要以文本格式存储它,因此您可能需要加密然后使用Base64对其进行编码) 。

\n