Як зашифрувати паролі stack overflow російською

Для початку треба зрозуміти, що хешування - це не шифрування. Хешрованіе пароля на клієнті ніяк не замінює шифрування, і ніяк не дозволяє захиститися від перехоплення трафіку. При передачі та пароля / його хеша (якщо дуже хочеться написати велосипед на JS) ніяк не замінює шифрування. Вам варто використовувати HTTPS. Всі інші способи, включаючи самопісний асиметричне шифрування - ненадійні.

Хешування захищає тільки від витоку даних з бази. Основна проблема при такому витоку - можливість відновити паролі по хешу і використовувати їх для password reuse attack - спробувати зайти з тим же email / username / password на популярні сервіси. Наприклад, на Github. Тобто ви змусите користувачів не тільки змінити пароль на свій сервіс, але і поміняти пароль на всі інші сервіси (так, недобре використовувати всюди один і той же пароль, але все так роблять!)

З цього прямо випливають вимоги до хешування:

  1. Злодій не повинен мати можливість швидко відновити популярні паролі по хешу. Використання популярного MD5 / SHA1 дозволяє швидко відновити паролі. 5f4dcc3b5aa765d61d8327deb882cf99 розшифрує з першого разу будь онлайновий сервіс.
  2. Злодій не повинен мати можливість відновити перебором паролі для всіх користувачів відразу. Один і той же пароль, використаний різними пользователемі, повинен дати різний хеш. Це збільшить час на розшифровку пропорційно кількості користувачів.

Є надійний стандартний спосіб вирішити відразу обидві проблеми - Key Derivation Function (Функція формування ключа).

  1. При первинному хешування згенерувати рандомноє значення - сіль, і порахувати хеш від "сіль + пароль". Використану сіль зберігати як частина результату.
  2. При перевірці пароля - хешірованного "сіль + перевіряється пароль", і порівнювати зі значенням, отриманим в (1).

Такий підхід дає різні значення навіть в тому випадку, якщо один користувач двічі використовує один і той же пароль.

В .NET є готові резалізаціі KDF, наприклад Rfc2898DeriveBytes. Використовується приблизно так: