Как хранить пароли в приложении Winforms?
Вопрос
У меня есть такой код в приложении winforms, которое я писал для запроса почтового ящика пользователя Квота хранилища.
DirectoryEntry mbstore = new DirectoryEntry(
@"LDAP://" + strhome,
m_serviceaccount,
[m_pwd],
AuthenticationTypes.Secure);
Независимо от того, какой подход я пробовал (например, SecureString
), я легко могу увидеть пароль ( m_pwd ) либо с помощью Reflector, либо с помощью вкладки строк в Process Explorer для исполняемый файл.
Я знаю, что мог бы разместить этот код на сервере или повысить безопасность, используя такие механизмы, как делегирование, и предоставляя только необходимые привилегии учетной записи службы.
Кто-нибудь может предложить достаточно безопасный способ хранения пароля в локальном приложении, не раскрывая пароль хакерам?
Хеширование невозможно, так как мне нужно знать точный пароль (а не только хеш для сопоставления). Механизмы шифрования / дешифрования не работают, поскольку они зависят от машины.
Решение
Освященный метод заключается в использовании 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, его сможет получить любой, у кого есть доступ к компьютеру.
Другие советы
Как уже упоминалось, API защиты данных является хорошим способом сделать это. Обратите внимание, что если вы используете .NET 2.0 или выше, вам не нужно использовать P / Invoke для вызова DPAPI. Инфраструктура упаковывает вызовы с помощью класса System.Security.Cryptography.ProtectedData.
Я нашел эту книгу. Кит Браун. Руководство разработчика по .NET по безопасности Windows. Он имеет несколько хороших примеров, охватывающих все виды сценариев безопасности. Бесплатная онлайн-версия также доступна.
Если вы храните ее как защищенную строку и сохраняете защищенную строку в файл (возможно, используя Изолированное хранилище , единственный раз, когда у вас будет простой текстовый пароль, это когда вы расшифровываете его для создания своего хранилища. К сожалению, конструктор не принимает SecureString или объект Credential. р>