Я хочу использовать SHA512 для хранения паролей. Для этого, какой из openssl_digest
, hash
и hash_hmac
следует использовать и почему?
В чем разница между SALT
& HMAC
?
Я просто прочитал, что HMAC построен поверх хэш-функции.
Итак, SHA512+SALT+HMAC
действительно необходим или SHA512+SALT
или SHA512+HMAC
?
Итак, во-первых, давайте разберемся. openssl_digest()
=== hash()
. Это просто другая функция с другим именем, которое делает то же самое. Он вычисляет криптографический хеш ввода.
Итак, теперь у нас возникает вопрос: при хранении паролей, что лучше: hash
или hash_hmac
?
ни
Как оказалось, The Rainbow Table Is Dead . Просто использование hash($password . $salt)
hash_hmac($password, $salt)
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
использует два хэш-цикла каждый раз, когда он hash_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
…
После недавних уроков LinkedIn , LastFM , Hotmail , Gawker и т. Д. Доказательство очевидно, что многие люди делают это неправильно. Не делайте это неправильно, используйте библиотеку с проверенным алгоритмом. Используйте CRYPT_BLOWFISH
(bcrypt), используйте PHPASS, используйте PasswordLib . Но не придумывайте свои собственные, потому что вы не хотите тянуть зависимость … Это просто халатность.
Больше информации:
HMAC – это особый способ использования хэш-алгоритма (например, SHA512). Он используется для подписания сообщения, и вы можете проверить, что сообщение от конкретного подписывающего лица и не было изменено. Так что это не то, что вы хотите.
Соль используется, чтобы добавить немного «случайности» в текст, который должен быть зашифрован или хэширован. Дело в том, что даже если вы зашифруете один и тот же текст несколько раз, вы получите разные результаты. Это затрудняет некоторые атаки. Это то, что вы хотите: SHA512(salt+password)
.
Для хранения паролей самым безопасным способом я мог бы представить:
(отказ от ответственности: я не очень разбираюсь в криптографии, и может быть лучшее решение)
Чтобы проверить пароль, выполните следующие действия:
Конечно, вы можете передавать пароль в виде открытого текста и делать все соление и хеширование на сервере, но это значительно ослабит ваше решение. Вы никогда не должны передавать пароль в текстовом виде.
Но проблема «передать соль клиенту» может быть проблемой. Один из способов, который я мог бы себе представить, – это как-то вывести соль из имени пользователя (проще всего: просто ввести lowercase(username) + password
), но проблема в том, что соль будет предсказуемой и, таким образом, решение немного. Тем не менее, это все еще лучше, чем передача «сырого» хеша, и вам даже не нужно было бы хранить соль, поскольку вы могли бы извлекать ее из имени пользователя каждый раз. Если ваш пароль DB будет украден, он все равно будет противостоять атаке радужного стола с помощью этого подхода «солить с именем пользователя».
Проблема в том, что атака «человек в середине» по-прежнему возможна. Если злоумышленник перехватывает имя пользователя и хеш, он имеет всю соответствующую информацию, и он не будет отличаться от передачи пароля открытого текста. Таким образом, вы можете защитить соединение с SSL (HTTPS).
По мнению экспертов ИТ-безопасности:
Использовать Bcrypt Источник: https://security.stackexchange.com/a/10905/7599 .
Я бы дал ответ в соответствии с точкой зрения SO.
openssl_digest vs hash vs hash_hmac
В криптографии хэш-код аутентификации сообщения (HMAC) представляет собой конкретную конструкцию для вычисления кода аутентификации сообщения (MAC), включающего криптографическую хеш-функцию в сочетании с секретным ключом.
Как сказал ircmaxell, hash
или hash_hmac
не лучше для хранения паролей с SHA-512. Я бы сказал, вы можете использовать openssl_digest
для хранения паролей.
См. Библиотеку SHA-512 для PHP
SALT vs HMAC
HMAC предназначен для использования в случаях, когда у вас есть случайный и секретный ключ. Для этих случаев HMAC обычно лучше, чем другие способы включения ключа в хеш-функцию. (Например, использование HMAC заботится о таких вещах, как атаки на расширение и т. Д.)
Соль обычно является случайным значением, которое не является секретом. То есть, когда вы используете термин соль, вы обычно ссылаетесь на ситуации, где есть случайное значение, которое может быть хорошо известно злоумышленнику. Поэтому безопасность системы не должна зависеть от сохранения соли в секрете. В этих ситуациях HMAC часто не очень хороший выбор.
Сравнение HMAC и Salt не является логичным. Лично я использовал соль и функцию хеша … и я не был бы параноик о силе хеш-функции, так как вряд ли она будет слабым звеном в любой практической системе ….
См. http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html.