Лучшие практики для шифрования и дешифрования паролей? (С # /. NET) - PullRequest
21 голосов
/ 24 апреля 2009

Мне нужно сохранить и зашифровать пароль в (желательно текстовом) файле, который позже мне понадобится расшифровать. Пароль для другой службы, которую я использую, и должен быть отправлен там в виде открытого текста (через SSL). Это не то, что я могу изменить. Каковы лучшие практики в этой области? Как можно добиться некоторой степени защиты пароля от злоумышленников?

Моя платформа - WinForms с C # /. NET 3.5.

Спасибо.

Ответы [ 9 ]

13 голосов
/ 24 апреля 2009

Я предполагаю, что вы хотите зашифровать пароль, который будет на компьютере пользователя, и они (возможно) смогут его найти и использовать? Если это так, то вы в основном испорчены - независимо от того, что вы делаете, поскольку именно в домене пользователей они смогут получить его, выяснить шифрование и получить пароль для шифрования (помните, что использование Reflector - и его клонов - isn недосягаем для большинства) и расшифровать его, и они есть. Короче говоря, все, что вы делаете - это запутываете пароль, а не защищаете его.

Что я бы порекомендовал, так это вывести его из-под контроля пользователей. Например, установите веб-сервис, который связывается с клиентом и безопасно возвращает пароль по запросу. Это также позволяет вам изменить пароль, если это необходимо в будущем, а также дает вам возможность проверять законных пользователей.

7 голосов
/ 24 апреля 2009

Зачем вам нужно расшифровывать пароль? Обычно соленый хеш пароля сохраняется и сравнивается. Если вы зашифруете / расшифруете пароль, у вас снова будет пароль в виде простого текста, и это опасно. Хеш должен быть засолен, чтобы избежать дублирования хэша, если некоторые пользователи имеют одинаковые пароли. За соль вы можете взять имя пользователя.

HashAlgorithm hash = new SHA256Managed();
string password = "12345";
string salt = "UserName";

// compute hash of the password prefixing password with the salt
byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password);
byte[] hashBytes = hash.ComputeHash(plainTextBytes);

string hashValue = Convert.ToBase64String(hashBytes);

Вы можете вычислить соленый хеш пароля и сохранить его в своем файле. Во время аутентификации вы снова вычисляете хеш из записей пользователя и сравниваете этот хеш с хешем сохраненного пароля. Поскольку получение простого текста из хеша должно быть очень трудным (никогда не невозможным, всегда делом времени), пароль защищен от повторного чтения в виде простого текста.

Совет. Никогда не храните и не отправляйте незашифрованный пароль. Если вы получите новый пароль, зашифруйте как можно скорее!

6 голосов
/ 24 апреля 2009

System.Security.Cryptography.ProtectedData в сборке System.Security использует некоторые API-интерфейсы Windows для шифрования данных только с помощью пароля, который он знает.

Одним из возможных применений этого было бы использование службы Windows, которая фактически выполняет операцию, требующую пароля. Приложение, которое пользователь взаимодействует с вызовами в службу через удаленное взаимодействие или WCF. Пока служба использует DataProtectionScope.CurrentUser и пользователь службы отличается от пользователя, вошедшего в систему, пароль должен быть достаточно безопасным.

Это, конечно, предполагает, что пользователи работают как пользователи с ограниченными правами, которые не могут изменять службу или запускать программу как пользователь службы.

2 голосов
/ 24 апреля 2009

Поскольку вы используете WinForms и .Net, ваш код будет виден в MSIL - даже если он запутан, и, следовательно, ваш код дешифрования виден.

От кого вы пытаетесь скрыть пароль? Пользователь приложения не должен знать пароль?

Я думаю, что вам понадобится выполнить некоторую проверку пользователя, и у меня будет соблазн поместить ключи для дешифрования в отдельную базу данных и предоставить какой-то другой механизм для его получения, который должен требовать аутентификации. Таким образом, вы можете получить код расшифровки из приложения winforms.

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

1 голос
/ 04 сентября 2009

Я только что реализовал что-то вроде этого для хранения предоставленного пользователем пароля. Я преобразовал зашифрованный результат в строку, закодированную в формате base 64, чтобы его можно было легко сохранить в пользовательских настройках приложения.

Судя по вашему вопросу, кажется, что ваш злоумышленник фактически использует ваше приложение, так что это только обеспечит запутывание. Хотя при использовании Reflector не будет обнаружено ни одного ключа, простой текст будет виден в отладчике.

static byte[] entropy = { 65, 34, 87, 33 };

public string Password
{
    get
    {
        if (this.EncryptedPassword == string.Empty)
        {
            return string.Empty;
        }

        var encrypted = Convert.FromBase64String(this.EncryptedPassword);
        var data = ProtectedData.Unprotect(encrypted, entropy, DataProtectionScope.CurrentUser);
        var password = Encoding.UTF8.GetString(data);
        return password;
    }
    set
    {
        if (value == string.Empty)
        {
            this.EncryptedPassword = string.Empty;
            return;
        }

        var data = Encoding.UTF8.GetBytes(value);
        var encrypted = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);
        var stored = Convert.ToBase64String(encrypted);
        this.EncryptedPassword = stored;
    }
}
1 голос
/ 24 апреля 2009

Зашифровано в AES, если необходимо сохранить его в текстовом файле.

AES более известен как Rijndael в c #

http://www.obviex.com/samples/Encryption.aspx

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

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

Или существует System.Security.Cryptography.ProtectedData, которую кто-то предложил.

Лучшее, что вы можете сделать на машине, - это создать сертификат и зашифровать / расшифровать его, загрузив и заблокировав в хранилище ключей машины. (Все равно придется иметь дело с паролем сертификата, который находится в вашем коде)

0 голосов
/ 24 апреля 2009

Поскольку вы должны отправить пароль в незашифрованном виде по сети, вы ничего не можете сделать, чтобы защитить его на 100%.

AES достаточно хорош, если вам нужно хранить локально, и разговоры о бедствиях, сетевых снифферах и т. Д. Не особенно хороший контраргумент, потому что то же самое можно сделать с любой программой (конечно, ASM сложнее, чем CIL, но это второстепенный пункт).

Такая защита паролем достаточно хороша для предотвращения случайного подбора, а не для предотвращения декодирования профессионалами.

0 голосов
/ 24 апреля 2009

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

0 голосов
/ 24 апреля 2009

Не храните пароль как часть кода. Помимо вопросов декомпиляции и обеспечения безопасности из-за неясности, если вы меняете пароль, вам необходимо перекомпилировать и перераспределить ваше приложение.

Сохраните пароль как веб-сервис или в базе данных, к которой у приложения есть доступ. Вы общаетесь со службой через Интернет, так что в конце концов вы будете на связи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...