Openssl_digest vs hash vs hash_hmac? Разница между SALT & HMAC?

Я хочу использовать SHA512 для хранения паролей. Для этого, какие из openssl_digest, hash и hash_hmac следует использовать и почему?

В чем разница между SALT и HMAC?

Я просто прочитал, что HMAC построен поверх хэш-функции.

Итак, действительно необходимо SHA512+SALT+HMAC или SHA512+SALT или SHA512+HMAC?

3 ответа

Итак, во-первых, позвольте мне разобраться. openssl_digest() === hash(). Это просто другая функция с другим именем, которое делает то же самое. Он вычисляет криптографический хеш ввода.

Итак, теперь у нас возникает вопрос: при сохранении паролей, что лучше: hash или hash_hmac?

Краткий ответ:

Ни

Длинный ответ:

Как оказалось, The Rainbow Table Is Dead. Просто использовать hash($password . $salt) или даже hash_hmac($password, $salt) недостаточно для хранения паролей. Период. Если вы это сделаете, остановитесь прямо сейчас.

Причина проста: время вычислений на компьютере (или графическом процессоре) невероятно дешево. Это так дешево, что для грубой силы список паролей достаточно дешев, что вам нужно беспокоиться об этом. Помните, что функции хэша рассчитаны на быструю работу. Не дорого...

Но, как выясняется, есть способ сделать эти быстрые хеш-функции более дорогими. На самом деле это довольно просто: итерация.

Теперь я знаю, о чем вы думаете. Вы просто перейдете через хэш:

function hash_password($password, $salt) {
 $hash = hash("sha512", $password . $salt);
 for ($i = 0; $i < 1000; $i++) {
 $hash = hash("sha512", $hash);
 }
}

Конечно, это достаточно хорошо, не так ли? Неа. Как объяснено в Основном Различия между Хешированием и Шифрованием, это не очень хорошая идея. Так почему бы просто не вернуть обратно пароль и соль снова?

function hash_password($password, $salt) {
 $hash = hash("md5", $salt . $password);
 for ($i = 0; $i < 1000; $i++) {
 $hash = hash("md5", $hash . $password);
 }
}

Фактически, это именно то, что использует PHPASS (слегка измененный, но это базовый алгоритм)...

Итак, теперь 1 вызов hash_password выполняет 1000 циклов хеширования.

Но можем ли мы улучшить это?

Ну, как выясняется, мы можем. Следующей логической задачей было бы увидеть, можем ли мы получить больше циклов хеширования за такое же количество времени. И здесь приходит hash_hmac(). Как оказалось, HMAC использует два хэш-цикла каждый раз, когда он вызывал. И поскольку все это C, это занимает примерно в 1,5 раза больше времени, которое hash() принимает для выполнения одного раунда.

Таким образом, это означает, что если мы заменим hash на hash_hmac, мы сразу увидим 33% -ное увеличение количества работы, выполняемой за указанное время. Итак, теперь мы здесь:

function hash_password($password, $salt) {
 $hash = hash_hmac("md5", $salt, $password);
 for ($i = 0; $i < 1000; $i++) {
 $hash = hash_hmac("md5", $hash, $password);
 }
}

И на самом деле это основной внутренний цикл PBKDF2.

Но можем ли мы поправляться?

Да, опять же, мы можем поправляться. Если мы посмотрим внимательно, мы увидим, что, помимо пароля и соли, все эти алгоритмы используют очень небольшой объем памяти. В случае sha512 они будут использовать от 128 до 256 байтов (буферы и состояние) для хеширования пароля. Поскольку использование памяти настолько мало, тривиально запускать много из них одновременно бок о бок в графическом процессоре. Если бы мы могли увеличить использование памяти...

Ну, как оказалось, мы можем просто использовать bcrypt, который является адаптивным алгоритмом хэширования. Он имеет преимущество в том, что он использует больше памяти, чем вышеупомянутые алгоритмы (порядка от 4 до 5kb). Таким образом, он более устойчив к распараллеливанию. И он сопротивляется жестокому форсированию, поскольку он вычислительно дорогой.

К счастью, он доступен для PHP:

crypt($password, '$2y$07$usesomesillystringforsalt$')

Обратите внимание, что crypt() использует множество алгоритмов, но алгоритмы $2y$ и $2a$ bcrypt.

Но можем ли мы улучшить это?

Вид-оф. Существует относительно новый алгоритм, называемый scrypt. Это лучше, чем bcrypt, потому что он так же дорого стоит вычислить, но использует LOT больше памяти (от порядка 20 мб до 40 мб для хеширования одного пароля). Поэтому он еще более устойчив к распараллеливанию...

К сожалению, scrypt пока недоступен в PHP (я работаю над его изменением). До тех пор используйте bcrypt...

Sidenote

После недавних уроков из LinkedIn, LastFM, Hotmail, Gawker и т.д., очевидно, что много людей делают это неправильно. Не делайте это неправильно, используйте библиотеку с проверенным алгоритмом. Используйте CRYPT_BLOWFISH (bcrypt), используйте PHPASS, используйте PasswordLib. Но не изобретайте свои собственные, потому что вы не хотите тянуть зависимость... Это просто халатность.

Дополнительная информация:


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

A salt используется для добавления бит "случайности" в текст, который должен быть зашифрован или хэширован. Дело в том, что даже если вы зашифруете один и тот же текст несколько раз, вы получите разные результаты. Это затрудняет некоторые атаки. Это то, что вы хотите: SHA512(salt+password).

Для хранения паролей самым безопасным способом я мог бы предположить:

(отказ от ответственности: я не очень разбираюсь в криптографии, и может быть лучшее решение)

  • Клиент (код JavaScript?) будет генерировать значение соли.
  • Затем клиент объединяет соль и пароль и запускает результат с помощью вашего алгоритма хеширования.
  • Затем клиент передает значение соли и хеша на сервер, который хранит его (предпочтительно в разных местах).

Чтобы проверить пароль, выполните следующие действия:

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

Конечно, вы можете передавать пароль в виде открытого текста и делать все соление и хеширование на сервере, но это значительно ослабит ваше решение. Вы никогда не должны передавать пароль в виде открытого текста.

Но часть "передать соль клиенту" может быть проблемой. Один из способов, который я мог бы себе представить, - это как-то извлечь соль из имени пользователя (проще всего: просто сделать lowercase(username) + password), но проблема в том, что соль будет предсказуемой и, таким образом, немного ослабнет ваше решение немного. Тем не менее, это все еще лучше, чем передача "сырого" хеша, и вам даже не нужно было бы хранить соль, поскольку вы могли бы извлекать ее из имени пользователя каждый раз. Если ваш пароль DB будет украден, он все равно будет сопротивляться атаке радужного стола с помощью этого подхода "солить с именем пользователя".

Проблема в том, что атака "человек в середине" по-прежнему возможна. Если злоумышленник перехватывает имя пользователя и хеш, он имеет всю соответствующую информацию, и он не будет отличаться от передачи пароля открытого текста. Таким образом, вы можете защитить соединение с SSL (HTTPS).


По мнению экспертов ИТ-безопасности:

Используйте Bcrypt Источник: https://security.stackexchange.com/a/10905/7599.

Я бы дал ответ в соответствии с SO точкой зрения.

openssl_digest vs hash vs hash_hmac
  • openssl_digest - вычисляет дайджест.
  • hash Создать хэш-значение (дайджест сообщения)
  • hash_hmac - Создайте хеш-значение с ключом, используя метод HMAC

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

Как сказано ircmaxell, hash или hash_hmac не лучше хранить пароли с SHA-512. Я бы сказал, вы можете использовать openssl_digest для хранения паролей.

Смотрите библиотеку SHA-512 для PHP

SALT vs HMAC
  • Хэш в этом контексте является односторонней функцией - то есть функцией, которая очень легко находит результат из аргумент (пароль), но трудно (или невозможно) найти любой аргумент, который генерирует данный результат.
  • A salt - это некоторые вспомогательные данные, которые дополняют аргумент хэш-функции. Это полезно, поскольку это предотвращает случайное обнаружение паролей через наблюдение, что два хэшированных пароля имеют одинаковые значения. С солью сохраненное/переданное значение будет только идентичным, если совпадают соль и пароль.
  • HMAC относится к приложению хеша (и дополнительной соли) к "коду аутентификации сообщения", который, в зависимости от по контексту может быть пароль... или, по крайней мере, там ничего не мешает вам передавать пароль в HMAC, как если бы это был код аутентификации сообщения.

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

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

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

См. http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html

licensed under cc by-sa 3.0 with attribution.