Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1423. #BestPractices Хеширование Паролей в C#. Окончание Начало Пример хеширования с помощью PBKDF2 Мы будем использовать статический метод Rfc2898DeriveBytes.Pbkdf2(). Он принимает несколько параметров, включая соль. Чтобы сгенерировать правильную случайную соль, воспользуемся статическим методом RandomNumberGenerator.GetBytes():
const int keySize = 64;
const int iterations = 350000;
var hashAlgorithm = HashAlgorithmName.SHA512;
string HashPasword(string password, out byte[] salt)
{
  salt = RandomNumberGenerator.GetBytes(keySize);
  var hash = Rfc2898DeriveBytes.Pbkdf2(
      Encoding.UTF8.GetBytes(password),
      salt,
      iterations,
      hashAlgorithm,
      keySize);
  return Convert.ToHexString(hash);
}

Функция HashPassword() принимает пароль в виде открытого текста и возвращает его хешированную версию. Мы получаем случайную соль, сгенерированную в процессе, через выходной параметр salt. Важно получить и сохранить эту часть данных, так как она необходима для последующей проверки пароля. keySize - желаемый размер в байтах результирующего хэша и размер случайной соли. Мы должны согласовать это значение с размером хэша, который производит базовый алгоритм хеширования. PBKDF2 можно применять несколько раз к заданному входному значению для усиления результирующего хэша, поэтому добавим константу iterations. Считается, что безопасные значения для производственных сред исчисляются сотнями тысяч. Наконец, в переменной hashAlgorithm определяем базовый метод хеширования, который PBKDF2 будет использовать для вывода, в данном случае SHA512. Пример использования:
var hash = 
 HashPasword("clear_password", out var salt);
Console.WriteLine($"Hash: {hash}");
Console.WriteLine($"Salt: {Convert.ToHexString(salt)}");

Проверка пароля Т.к. мы не можем расшифровать хеш-алгоритмы, нужно снова хешировать входящий пароль и сравнивать результат с сохранённой хешированной версией:
bool VerifyPassword(
 string password,
 string hash,
 byte[] salt)
{
  var hashToCompare = 
   Rfc2898DeriveBytes.Pbkdf2(
    password, salt, iterations, 
    hashAlgorithm, keySize);

  return hashToCompare.SequenceEqual(
   Convert.FromHexString(hash));
}

Функция VerifyPassword() принимает чистый пароль, сохранённый хэш пароля и связанную с ним соль. Она вернет true, если предоставленный чистый пароль сгенерирует тот же хэш. Очень важно предоставить те же значения для iterations, hashAlgorithm и keySize, что и при начальном хешировании. Другие классы и библиотеки BCrypt.Net-Next — сторонняя библиотека для хеширования паролей, основанная на алгоритме BCrypt. Класс PasswordHasher<TUser> является частью пакета Microsoft.AspNetCore.Identity, который реализует хеширование и проверку паролей на основе PBKDF2 со случайными значениями соли и итераций. Источник: https://code-maze.com/csharp-hashing-salting-passwords-best-practices/