如何在Winforms应用程序中存储密码?

时间:2020-03-05 18:46:48  来源:igfitidea点击:

我在编写用于查询用户邮箱存储配额的winforms应用程序中有这样的代码。

DirectoryEntry mbstore = new DirectoryEntry(
      @"LDAP://" + strhome, 
      m_serviceaccount, 
      [m_pwd], 
      AuthenticationTypes.Secure);

无论我尝试了哪种方法(例如SecureString),都可以使用Reflector或者使用Process Explorer的可执行文件的"字符串"选项卡轻松查看密码(m_pwd)。

我知道我可以将此代码放在服务器上,或者使用委派之类的机制并仅将所需的特权赋予服务帐户来加强安全性。

有人可以建议一种合理安全的方法来将密码存储在本地应用程序中,而不向黑客透露密码吗?

散列是不可能的,因为我需要知道确切的密码(不仅仅是用于匹配目的的散列)。
加密/解密机制不起作用,因为它们取决于计算机。

解决方案

回答

如果将其存储为安全字符串并将该安全字符串保存到文件中(可能使用隔离存储,则只有当我们解密它以创建mbstore时,才会有纯文本密码。不幸的是,构造方法并不需要使用SecureString或者凭据对象。

回答

公认的方法是使用CryptoAPI和数据保护API。

要加密,请使用类似以下内容的代码(C ++):

DATA_BLOB blobIn, blobOut;
blobIn.pbData=(BYTE*)data;
blobIn.cbData=wcslen(data)*sizeof(WCHAR);

CryptProtectData(&blobIn, description, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE | CRYPTPROTECT_UI_FORBIDDEN, &blobOut);
_encrypted=blobOut.pbData;
_length=blobOut.cbData;

解密是相反的:

DATA_BLOB blobIn, blobOut;
blobIn.pbData=const_cast<BYTE*>(data);
blobIn.cbData=length;

CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &blobOut);

std::wstring _decrypted;
_decrypted.assign((LPCWSTR)blobOut.pbData,(LPCWSTR)blobOut.pbData+blobOut.cbData/sizeof(WCHAR));

如果我们未指定CRYPTPROTECT_LOCAL_MACHINE,则加密的密码可以安全地存储在注册表或者配置文件中,只有我们才能解密。如果指定LOCAL_MACHINE,那么有权访问该计算机的任何人都可以得到它。

回答

我是keith Brown所著的《 Windows安全.NET开发人员指南》。它具有一些涵盖各种安全方案的良好示例。
还提供免费的在线版本。

回答

如前所述,Data Protection API是执行此操作的好方法。请注意,如果我们使用的是.NET 2.0或者更高版本,则无需使用P / Invoke来调用DPAPI。该框架使用System.Security.Cryptography.ProtectedData类包装这些调用。