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.
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.
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.
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.
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.