День 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/