How to store passwords in Winforms application?

2019-01-07 06:55发布

问题:

I have some code like this in a winforms app I was writing to query a user's mail box Storage Quota.

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

No matter what approach I tried (like SecureString), I am easily able to see the password (m_pwd) either using Reflector or using strings tab of Process Explorer for the executable.

I know I could put this code on the server or tighten up the security using mechanisms like delegation and giving only the required privileges to the service account.

Can somebody suggest a reasonably secure way to store the password in the local application without revealing the password to hackers?

Hashing is not possible since I need to know the exact password (not just the hash for matching purpose). Encryption/Decryption mechanisms are not working since they are machine dependent.

回答1:

The sanctified method is to use CryptoAPI and the Data Protection APIs.

To encrypt, use something like this (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;

Decryption is the opposite:

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));

If you don't specify CRYPTPROTECT_LOCAL_MACHINE then the encrypted password can be securely stored in the registry or config file and only you can decrypt it. If you specify LOCAL_MACHINE, then anyone with access to the machine can get it.



回答2:

As mentioned, the Data Protection API is a good way to do this. Note that if you're using .NET 2.0 or greater, you don't need to use P/Invoke to invoke the DPAPI. The framework wraps the calls with the System.Security.Cryptography.ProtectedData class.



回答3:

I found this book by keith Brown The .NET Developer's Guide to Windows Security. It has some good samples covering all kinds of security scenarios. Free Online version is also available.



回答4:

If you store it as a secure string and save the secure string to a file (possibly using Isolated Storage, the only time you will have a plain text password is when you decrypt it to create your mbstore. Unfortunately, the constructor does not take a SecureString or a Credential object.