Что делать, если вы не можете сохранить пароль как хеш - PullRequest
8 голосов
/ 16 февраля 2010

У меня есть программа, которая использует System.DirectoryServices.AccountManagement.PrincipalContext для проверки того, что информация, введенная пользователем на экране настройки, является действительным пользователем в домене (сам компьютер не находится в домене) и выполняет некоторые операции над пользователямидомен.Проблема в том, что я не хочу, чтобы пользователю приходилось вводить свой пароль каждый раз, когда он запускает программу, поэтому я хочу сохранить его, но я не чувствую себя комфортно, сохраняя пароль в виде простого текста в своем файле app.config.PrincipalContext нужен простой текстовый пароль, поэтому я не могу сделать соленый хеш, как все рекомендуют для хранения пароля.

Это то, что я сделал

const byte[] mySalt = //It's a secret to everybody.
[global::System.Configuration.UserScopedSettingAttribute()]
public global::System.Net.NetworkCredential ServerLogin
{
    get
    {
        var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"]));
        if(tmp != null)
            tmp.Password = new System.Text.ASCIIEncoding().GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), mySalt, DataProtectionScope.CurrentUser));
        return tmp;
    }
    set
    {
        var tmp = value;
        tmp.Password = Convert.ToBase64String(ProtectedData.Protect(new System.Text.ASCIIEncoding().GetBytes(tmp.Password), mySalt, DataProtectionScope.CurrentUser));
        this["ServerLogin"] = value;
    }
}

Было ли это правильным решениемЕсть ли лучший способ?

РЕДАКТИРОВАТЬ - Вот обновленная версия на основе предложений каждого

private MD5 md5 = MD5.Create();

[global::System.Configuration.UserScopedSettingAttribute()]
public global::System.Net.NetworkCredential ServerLogin
{
    get
    {
        var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"]));
        if(tmp != null)
            tmp.Password = System.Text.Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser));
        return tmp;
    }
    set
    {
        var tmp = value;
        tmp.Password = Convert.ToBase64String(ProtectedData.Protect(System.Text.Encoding.UTF8.GetBytes(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser));
        this["ServerLogin"] = tmp;
    }
}

Ответы [ 3 ]

4 голосов
/ 16 февраля 2010

Для соли я бы сделал преобразование имени пользователя (хэш), а не разделил бы одну соль для всех.

Для чего-то подобного я бы также искал способ сохранить существующий сеанс дольше, а не сохранять пароль для создания новых сеансов.

2 голосов
/ 16 февраля 2010

Вместо записи new System.Text.ASCIIEncoding(), вы должны написать System.Text.Encoding.ASCII.

Кроме того, я рекомендую использовать вместо UTF8.

Кроме того, ваш код выглядит довольно хорошо.

0 голосов
/ 16 февраля 2010

Мне нравится подход JoelCoehoorn.

Используйте значение, уникальное для пользовательского компьютера, в качестве соли пароля.

Так что это будет отличаться в каждом отделении; ).

ОБНОВЛЕНИЕ: см. Эту ветку для идей: Как получить уникальную подпись машины

...