Большинство других ответов здесь несколько устарели с лучшими на сегодняшний день практиками.В качестве такового здесь используется приложение PBKDF2 / Rfc2898DeriveBytes для хранения и проверки паролей.Следующий код находится в отдельном классе в этом посте: Еще один пример того, как хранить хэш соленого пароля .Основы действительно просты, поэтому здесь они разбиты:
ШАГ 1 Создание значения соли с помощью криптографического PRNG:
byte[] salt;
new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
ШАГ 2 Создайте Rfc2898DeriveBytes и получите значение хеша:
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
ШАГ 3 Объедините байты соли и пароля для последующего использования:
byte[] hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);
ШАГ 4 Превратить объединенный хэш соли + в строку для хранения
string savedPasswordHash = Convert.ToBase64String(hashBytes);
DBContext.AddUser(new User { ..., Password = savedPasswordHash });
ШАГ 5 Проверить введенный пользователем пароль против сохраненного пароля
/* Fetch the stored value */
string savedPasswordHash = DBContext.GetUser(u => u.UserName == user).Password;
/* Extract the bytes */
byte[] hashBytes = Convert.FromBase64String(savedPasswordHash);
/* Get the salt */
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
/* Compute the hash on the password the user entered */
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
/* Compare the results */
for (int i=0; i < 20; i++)
if (hashBytes[i+16] != hash[i])
throw new UnauthorizedAccessException();
Примечание. В зависимости от требований к производительности вашего конкретного приложения значение «10000» может быть уменьшено.Минимальное значение должно быть около 1000.