Ответ
Выбор алгоритма зависит от цели: хеширование паролей и создание криптографических подписей для токенов — это разные задачи.
1. Для хеширования паролей (должно быть медленным):
- PBKDF2 (Password-Based Key Derivation Function 2): Стандартный выбор в .NET. Использует множество итераций хеш-функции (например, SHA-256) вместе с "солью" (salt), что сильно замедляет перебор.
using System.Security.Cryptography; // Генерация хеша public byte[] HashPassword(string password, out byte[] salt) { salt = RandomNumberGenerator.GetBytes(32); // Уникальная соль для каждого пароля using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 600000, HashAlgorithmName.SHA256); return pbkdf2.GetBytes(32); // 256-битный хеш } // Верификация public bool VerifyPassword(string password, byte[] storedHash, byte[] storedSalt) { using var pbkdf2 = new Rfc2898DeriveBytes(password, storedSalt, 600000, HashAlgorithmName.SHA256); byte[] testHash = pbkdf2.GetBytes(32); return CryptographicOperations.FixedTimeEquals(storedHash, testHash); // Сравнение, защищенное от атак по времени } - BCrypt / Argon2: Считаются более устойчивыми к атакам с использованием специализированного железа (ASIC/GPU). В .NET используются через сторонние библиотеки (например,
BCrypt.Net-Next).
2. Для подписи токенов (должно быть быстрым и криптостойким):
- HMAC-SHA256/512 (Hash-based Message Authentication Code): Основа для подписи JWT (JSON Web Tokens). Гарантирует, что токен не был изменен после выдачи.
using System.Security.Cryptography; // Создание подписи для данных public byte[] SignData(byte[] data, byte[] secretKey) { using var hmac = new HMACSHA256(secretKey); // Секретный ключ известен только серверу return hmac.ComputeHash(data); } - Асимметричная подпись (RSA, ECDSA): Используется, когда нужно, чтобы токен мог проверить любая сторона, имеющая открытый ключ, но подписать — только владелец закрытого ключа (например, в микросервисной архитектуре).
Ключевые принципы:
- Для паролей всегда используйте соль (уникальную для каждого пользователя) и адаптивные функции (большое число итераций).
- Секретные ключи для HMAC должны генерироваться криптографически стойким генератором и храниться в защищенном месте (Key Vault).
- Избегайте устаревших алгоритмов: MD5, SHA1 считаются небезопасными для этих целей.
Ответ 18+ 🔞
Давай разберёмся, что куда тыкать, а то народ путает как слепой кот в сортире. Смотри, тут два принципиально разных случая, и если их перепутать — будет тебе хиросима в продакшене, а не система.
1. Хеширование паролей (должно быть МЕДЛЕННЫМ, чтоб взломщики обосрались) Смысл в чём? Надо сделать такую операцию, чтобы проверка одного пароля у тебя занимала, скажем, 100 мс. Это ерунда для одного пользователя. А вот у подлеца, который купил ферму из 1000 видюх и пытается перебрать миллиарды вариантов, это будет пиздец как долго и дорого. Тут скорость — враг.
- PBKDF2 (Password-Based Key Derivation Function 2): Старый, добрый, проверенный тазик в .NET. Берёт обычный хеш (типа SHA-256) и долбит им по паролю с солью тысячи, а лучше сотни тысяч раз. От этого все устают, особенно брутфорс-боты.
using System.Security.Cryptography; // Генерация хеша public byte[] HashPassword(string password, out byte[] salt) { salt = RandomNumberGenerator.GetBytes(32); // Уникальная соль для каждого юзера! Без неё — вообще никуда. using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 600000, HashAlgorithmName.SHA256); // 600к итераций — не стесняйся return pbkdf2.GetBytes(32); // 256-битный хеш } // Проверка public bool VerifyPassword(string password, byte[] storedHash, byte[] storedSalt) { using var pbkdf2 = new Rfc2898DeriveBytes(password, storedSalt, 600000, HashAlgorithmName.SHA256); byte[] testHash = pbkdf2.GetBytes(32); return CryptographicOperations.FixedTimeEquals(storedHash, testHash); // Важно! Сравнение, защищённое от атак по времени, чтобы не светить, где ошибка. } - BCrypt / Argon2: Это уже круче. Они не только итерации делают, но ещё и память жрут как не в себя, что делает атаки на спецжелезе (типа ASIC или GPU) невыгодными. В .NET нет из коробки, но есть через
BCrypt.Net-Next. Если делать серьёзно — смотри в их сторону.
2. Подпись токенов (должно быть БЫСТРЫМ и надёжным) Тут задача другая. Ты выпускаешь JWT токен на 15 минут. Его нужно быстро подписать тебе и быстро проверить любому сервису, которому ты дашь ключ. Медлить тут нельзя, запросов много.
- HMAC-SHA256/512: Классика для JWT. Берёшь данные токена, секретный ключ (который знаешь только ты) и получаешь подпись. Изменишь хоть запятую в токене — подпись не сойдётся. Быстро и сердито.
using System.Security.Cryptography; // Создание подписи public byte[] SignData(byte[] data, byte[] secretKey) { using var hmac = new HMACSHA256(secretKey); // Этот ключ — твоя главная тайна. Храни как зеницу ока. return hmac.ComputeHash(data); } - Асимметричная подпись (RSA, ECDSA): Это когда у тебя есть парочка: приватный ключ (подписывает) и публичный (проверяет). Нужно, если твой API-шник должен проверять токен, но не должен уметь его создавать. Идеально для микросервисов, где один сервис выпускает, а десять других проверяют.
Главное, что нужно вынести, чтобы не быть распиздяем:
- Пароли: Соль + много итераций = PBKDF2/BCrypt/Argon2. Никакого SHA256 в лоб, ёпта! Это как хранить голый текст, только чуть хуже.
- Ключи для HMAC: Генерируй их через
RandomNumberGenerator, а неnew Random(), и прячь в Key Vault, а не в конфиг рядом с кодом. Доверия к файлуappsettings.json— ноль ебать. - Старьё: Забудь как страшный сон про MD5, SHA1. Они сломаны, их бьют как детей. Использовать их — это кричать всему миру «я мудак, блядь, нахуй идите ко мне в прод».
- Не изобретай велосипед: Не пытайся склеить PBKDF2 с HMAC или придумать свою «супер-защиту». Возьми готовый, проверенный боем алгоритм и правильно его настрой. Всё уже придумано до нас, и чаще всего — умными людьми, которые в этом шариют.
Вот так, коротко и без воды. Выбирай инструмент по задаче, а не потому что «в гайде на метаните так было».