openssl_digest против хеша против hash_hmac?Разница между солью и HMAC? - PullRequest
14 голосов
/ 21 января 2012

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


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


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

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

Ответы [ 3 ]

57 голосов
/ 25 июня 2012

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

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

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

Ни

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

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

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

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

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

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 использует 2 цикла хеширования при каждом вызове. И поскольку все это 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-5 КБ). Так что он более устойчив к распараллеливанию. И он устойчив к грубому принуждению, так как он вычислительно дорог.

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

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

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

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

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

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

Sidenote

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

Больше чтения:

7 голосов
/ 21 января 2012

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

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

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

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

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

Чтобы подтвердить пароль, вы должны сделать:

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

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

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

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

3 голосов
/ 26 июня 2012

По мнению экспертов по информационной безопасности:

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

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

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

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...