• аутентификация
  • пароль
  • безопасность
  • хеширование
  • bcrypt
  • argon2
  • sha1
  • sha2
  • вход
  • авторизация

Эволюция хэширования паролей

Вы, возможно, слышали советы по выбору алгоритмов хеширования паролей, но думали ли вы, почему они рекомендуются? В этой статье мы исследуем эволюцию алгоритмов хэширования паролей и причины, стоящие за ними.

Gao
Gao
Founder

Введение

Хеширование паролей, как и следует из названия, - это процесс расчета хеш-значения из пароля. Хеш-значение обычно хранится в базе данных, и во время процесса входа в систему (авторизации) рассчитывается хеш-значение введенного пользователем пароля и сравнивается с хеш-значением, хранящимся в базе данных. Если они совпадают, пользователь аутентифицирован.

Прежде чем мы погрузимся в эволюцию алгоритмов хэширования паролей, важно понять, почему это необходимо.

Пароли в открытом виде: серьезный риск для безопасности

Представьте себе ситуацию, когда вы являетесь пользователем веб-сайта, на котором вы зарегистрировали аккаунт. Однажды веб-сайт подвергается хакерской атаке, и база данных утекает. Если веб-сайт хранит пароли в открытом виде, хакер может напрямую получить доступ к вашему паролю. Поскольку многие люди используют один и тот же пароль на различных сайтах, хакер может использовать этот пароль, чтобы получить несанкционированный доступ к другим вашим учетным записям. Ситуация усугубляется, если вы используете один и тот же или похожий пароль для своей электронной почты, так как хакер может сбросить ваш пароль и захватить все свои связанные учетные записи.

Даже без утечки данных, в больших командах любой, у кого есть доступ к базе данных, может видеть пароли. По сравнению с другой информацией, пароли являются очень чувствительными, и вам определенно не хочется, чтобы кто-то имел доступ к ним.

Хранение паролей без хэширования - это новичковая ошибка. К сожалению, если вы ищете "утечку пароля в открытом виде", вы обнаружите, что такие крупные корпорации, как Facebook, DailyQuiz и GoDaddy, все сталкивались с утечками паролей в открытом виде. Вероятно, многие другие компании сделали ту же ошибку.

Кодирование против шифрования против хэширования

Эти три термина часто путают, но это разные понятия.

Кодирование

Кодирование - это первое, что нужно исключить при хранении паролей. Например, Base64 - это алгоритм кодирования, который преобразует двоичные данные в строку символов:

Знание алгоритма кодирования позволяет любому раскодировать закодированную строку и получить исходные данные:

Для хакеров большинство алгоритмов кодирования эквивалентны открытому тексту.

Шифрование

Прежде чем хэширование стало популярным, для хранения паролей использовалось шифрование, например, с помощью AES. Шифрование включает использование ключа (или пары ключей) для шифрования и дешифрования данных.

Проблема шифрования очевидна в термине «дешифрование». Шифрование обратимо, что означает, что если хакер получит ключ, он сможет расшифровать пароль и получить пароль в открытом виде.

Хэширование

Основное отличие между хэшированием, кодированием и шифрованием заключается в том, что хеширование невозможно обратить. Как только пароль хешируется, его нельзя расшифровать обратно в исходную форму.

В качестве владельца веб-сайта вам на самом деле не нужно знать сам пароль, достаточно, чтобы пользователь мог войти с правильным паролем. Процесс регистрации можно объяснить следующим образом:

  1. Пользователь вводит пароль.
  2. Сервис использует алгоритм хэширования для расчета хеш-значения пароля.
  3. Сервис хранит хеш-значение в базе данных.

Когда пользователь входит в систему, процесс следующий:

  1. Пользователь вводит пароль.
  2. Сервис использует тот же алгоритм хэширования для расчета хеш-значения пароля.
  3. Сервис сравнивает хеш-значение с хеш-значением, хранящимся в базе данных.
  4. Если хеш-значения совпадают, пользователь аутентифицирован.

Оба процесса избегают хранения паролей в открытом виде, и поскольку хэширование является необратимым, даже если база данных будет скомпрометирована, хакер сможет получить только хеш-значения, которые выглядят как случайные строки.

Начальный пакет алгоритмов хеширования

Хеширование может показаться идеальным решением для хранения паролей, но все не так просто. Чтобы понять почему, давайте исследуем эволюцию алгоритмов хэширования паролей.

MD5

В 1992 году Рон Ривест разработал алгоритм MD5, алгоритм сведения сообщения, который может вычислить 128-битное хеш-значение из любых данных. MD5 широко используется в различных сферах, включая хэширование паролей. Например, хеш-значение MD5 для «123456» будет:

Как уже упоминалось ранее, хеш-значение выглядит как случайная строка и необратимо. Кроме того, MD5 быстрый и легкий в реализации, что делает его самым популярным алгоритмом хэширования паролей.

Однако преимущества MD5 также являются его слабостями при хешировании паролей. Его скорость делает его уязвимым для атак перебора. Если у хакера есть список общих паролей и вашей персональной информации, он может рассчитать хеш значение MD5 каждой комбинации и сравнить их с хеш-значениями в базе данных. Например, он может объединить ваш день рождения с вашим именем или именем вашего питомца.

В наши дни компьютеры значительно мощнее, чем прежде, что упрощает перебор хеш-паролей MD5.

Семейство SHA

Так почему бы не использовать другой алгоритм, который генерирует более длинные хеш-значения? Семейство SHA кажется хорошим выбором. SHA-1 - это алгоритм хеширования, который генерирует 160-битные хеш-значения, а SHA-2 - это семейство алгоритмов хеширования, которые генерируют хеш-значения длиной 224 бита, 256 бита, 384 бита и 512 бита. Давайте посмотрим на хеш-значение SHA-256 для «123456»:

Хеш-значение SHA-256 намного длиннее, чем MD5, и оно также необратимо. Однако есть еще одна проблема: если вы уже знаете хеш-значение, как тот, что выше, и вы видите точно такое же хеш-значение в базе данных, вы знаете, что пароль - «123456». Хакер может создать список общих паролей и их соответствующих хеш-значений и сравнить их с хеш-значениями в базе данных. Этот список известен как радужная таблица.

Соль

Чтобы уменьшить атаки с использованием радужных таблиц, было введено понятие 'соли'. Соль - это случайная строка, которая добавляется к паролю перед хешированием. Например, если соль - это 'соль', и вы хотите использовать SHA-256 для хеширования пароля «123456» с солью, вместо того, чтобы просто делать:

Вы бы делали:

Как видите, результат совершенно отличается от хеширования без соли. Как правило, каждому пользователю при регистрации назначается случайная соль, которая хранится в базе данных наряду с хеш-значением. Во время процесса входа в систему соль используется для расчета хеш-значения введенного пароля, которое затем сравнивается со сохраненным хеш-значением.

Итерация

Несмотря на добавление соли, хеш-значение все еще подвержено атакам перебора по мере увеличения мощности оборудования. Чтобы усложнить задачу, можно ввести итерацию (т. е. многократное выполнение алгоритма хеширования). Например, вместо использования:

Вы могли бы использовать:

Увеличение числа итераций затрудняет перебор. Однако это также влияет на процесс входа в систему, поскольку он становится медленнее. Поэтому необходимо достичь баланса между безопасностью и производительностью.

Перерыв на полпути

Давайте сделаем перерыв и подведем итог характеристикам хорошего алгоритма хеширования паролей:

  • Необратимый (стойкость к уравнению изображения)
  • Трудно подвергнуть перебору
  • Устойчив к атакам с использованием радужных таблиц

Как вы уже могли заметить, для удовлетворения всех этих требований необходимы соль и итерация. Проблема в том, что ни MD5, ни семейство SHA не были специально разработаны для хеширования паролей; они широко используются для проверок целостности (или 'сообшения-дайджест'). В результате каждый сайт может иметь свою собственную реализацию соли и итерации, что затрудняет стандартизацию и миграцию.

Алгоритмы хеширования паролей

Чтобы решить эту проблему, были разработаны несколько алгоритмов хеширования, специально предназначенных для хеширования паролей. Давайте рассмотрим некоторые из них.

bcrypt

bcrypt - это алгоритм хеширования паролей, разработанный Нильсом Профосом и Дэвидом Мазьере. Он широко используется во многих языках программирования. Вот пример значени хеш bcrypt:

Хотя это выглядит как еще одна случайная строка, она содержит дополнительную информацию. Давайте разберемся:

  • Первый раздел $2y указывает алгоритм, который равен 2y.
  • Второй раздел $12 указывает количество итераций, которое составляет 12. Это означает, что алгоритм хеширования будет выполнен 2 12 = 4096 раз (итераций).
  • Третий раздел wNt7lt/xf8wRJgPU7kK2ju - это соль.
  • Последний раздел ГрирГК4гдбОНиСРдССоАксООнбилуу - это хеш-значение.

У bcrypt есть некоторые ограничения:

  • Максимальная длина пароля составляет 72 байта.
  • Соль ограничена 16 байтами.
  • Хеш-значение ограничено 184 битами.

Argon2

В свете дискуссий и ограничений существующих алгоритмов хеширования паролей в 2015 году был проведен конкурс на хеширование паролей. Пропустив подробности, давайте сосредоточимся на победителе: Argon2.

Argon2 - это алгоритм хеширования паролей, разработанный Алексом Бирюковым, Даниелем Дину и Дмитрием Ховратовичем. Он вводит несколько новых концепций:

  • Затруднение для памяти: алгоритм спроектирован так, чтобы его было трудно параллелить, что делает сложным перебор на графических процессорах.
  • Времязатратный: алгоритм разработан так, чтобы его было трудно оптимизировать, что делает сложным перебор на ASIC (Специализированные интегральные схемы).
  • Устойчив к побочным каналам: алгоритм разработан для устойчивости к атакам через побочные каналы, например, внешними атаками.

Существует две основные версии Argon2, Argon2i и Argon2d. Argon2i является самым безопасным против атак через побочные каналы, а Argon2d обеспечивает наибольшую устойчивость к атакам на взлом GPU.

-- Argon2

Вот пример хеш-значения Argon2:

Давайте разберемся:

  • Первый раздел $argon2i указывает алгоритм, который равен 'argon2i'.
  • Второй раздел $v=19 указывает версию, которая равна '19'.
  • Третий раздел $m=16,t=2,p=1 указывает затраты памяти, времени и степень параллельности, которые составляют '16', '2' и '1'.
  • Четвертый раздел $YTZ5ZnpXRWN5SlpjMHBDRQ - это соль.
  • Последний раздел $12oUmJ6xV5bIadzZHkuLTg - это хеш-значение.

В Argon2 максимальная длина пароля составляет 2 32 -1 байт, соль ограничена 2 32 -1 байтами, и хеш-значение ограничено 2 32 -1 байтами. Этого должно быть достаточно для большинства сценариев.

Argon2 теперь доступен на многих языках программирования, таких как node-argon2 для Node.js и argon2-cffi для Python.

Заключение

На протяжении многих лет алгоритмы хеширования паролей прошли значительную эволюцию. Мы обязаны сообществу безопасности за их десятилетия усилий, направленных на создание более безопасного интернета. Благодаря их вкладу разработчики могут уделить больше внимания созданию лучших услуг, не беспокоясь о безопасности хеширования паролей. Хотя достижение 100% безопасности в системе может быть недостижимым, мы можем использовать различные стратегии для минимизации связанных с этим рисков.

Если вы хотите избежать сложностей реализации аутентификации и авторизации, не стесняйтесь попробовать Logto бесплатно. Мы предоставляем безопасные (мы используем Argon2!), надежные и масштабируемые решения, позволяющие вам сосредоточиться на создании своего продукта.