Какой тип данных использовать для поля хешированного пароля и какой длины?

269

Я не уверен, как работает хеширование паролей (буду реализовывать его позже), но сейчас нужно создать схему базы данных.

Я думаю об ограничении паролей до 4-20 символов, но, как я понимаю, после шифрования хеш-строка будет иметь различную длину.

Итак, как хранить эти пароли в базе данных?

г-хозяин
источник
Также см. Фреймворк хеширования паролей в PHP для PHP . Его портативный и защищенный от ряда распространенных атак на пароли пользователей. Парень, который написал фреймворк (SolarDesigner), тот же, кто написал Джона Потрошителя и является судьей в конкурсе хэширования паролей . Таким образом, он знает кое-что о атаках на пароли.
jww
2
Пожалуйста, не устанавливайте верхний предел для ваших паролей. Вы их хешируете, для верхнего предела нет причины хранения. Если вы беспокоитесь о DoS-атаках с использованием хэша пароля, 1000 или 1024 - разумный верхний предел.
Ииридайн
зачем ограничивать длину пароля? По крайней мере, позвольте пользователю создать 100-символьный пароль :)
Andrew
4 символа - довольно опасная нижняя граница для паролей, так как они тривиальны для взлома. По крайней мере, используйте 8, но 14 или 16 гораздо лучше.
quikchange
Это очень старый вопрос с устаревшим ответом. Смотрите ответ Жиля для актуальных.
Келалака

Ответы:

448

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

Для паролей используйте алгоритм хеширования ключей, такой как Bcrypt или Argon2i. Например, в PHP используйте функцию password_hash () , которая по умолчанию использует Bcrypt.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

В результате получается строка из 60 символов, похожая на следующую (но цифры могут отличаться, поскольку она генерирует уникальную соль).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Используйте тип данных SQL CHAR(60)для хранения этой кодировки хэша Bcrypt. Обратите внимание, что эта функция не кодируется как строка шестнадцатеричных цифр, поэтому мы не можем так просто отменить ее, чтобы сохранить в двоичном виде.

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


Это зависит от используемого вами алгоритма хеширования. Хеширование всегда дает результат одинаковой длины, независимо от ввода. Типично представлять двоичный результат хеширования в тексте как последовательность шестнадцатеричных цифр. Или вы можете использовать UNHEX()функцию, чтобы уменьшить строку шестнадцатеричных цифр вдвое.

  • MD5 генерирует 128-битное хеш-значение. Вы можете использовать CHAR (32) или BINARY (16)
  • SHA-1 генерирует 160-битное хеш-значение. Вы можете использовать CHAR (40) или BINARY (20)
  • SHA-224 генерирует 224-битное хеш-значение. Вы можете использовать CHAR (56) или BINARY (28)
  • SHA-256 генерирует 256-битное хеш-значение. Вы можете использовать CHAR (64) или BINARY (32)
  • SHA-384 генерирует 384-битное хеш-значение. Вы можете использовать CHAR (96) или BINARY (48)
  • SHA-512 генерирует 512-битное хеш-значение. Вы можете использовать CHAR (128) или BINARY (64)
  • BCrypt генерирует зависящее от реализации 448-битное хеш-значение. Вам может понадобиться CHAR (56), CHAR (60), CHAR (76), BINARY (56) или BINARY (60)

С 2015 года NIST рекомендует использовать SHA-256 или выше для любых применений хеш-функций, требующих взаимодействия. Но NIST не рекомендует использовать эти простые хэш-функции для безопасного хранения паролей.

Меньшие алгоритмы хеширования имеют свое применение (например, для внутреннего применения, а не для обмена), но известно , что они могут быть взломаны .

Билл Карвин
источник
47
@Hippo: Пожалуйста, не используйте имя пользователя в качестве соли. Генерация случайной соли для каждого пользователя.
Билл Карвин
11
Да, нет причин не хранить его в одном ряду. Даже если злоумышленник получит доступ к вашей базе данных, он должен будет построить свою радужную таблицу на основе этой соли. И это такая же работа, как и угадывание пароля.
Билл Карвин
5
@SgtPooki: Вам нужен еще один столбец, чтобы хранить соль в открытом виде. Затем вы можете хэшировать пароль пользователя с той же солью, когда он вводит его, и сравнивать результат с хэш-дайджестом, хранящимся в таблице.
Билл Карвин
12
Если вы храните соль в той же таблице (или в любом другом месте с теми же правами доступа), нет причин не использовать имя пользователя в качестве соли, поскольку оно будет уникальным для каждого пользователя. Однако любая известная соль делает хеш криптографически слабее, чем если бы не было известной соли. Соль только добавляет ценность, если это также неизвестно.
fijiaaron
9
Я не понимаю сделку с известной солью против неизвестной. Если вы реализуете сайт - соль должна быть известна странице входа / script / sevice, которая проверяет пароль. Итак, вы - «неизвестные» сторонники соли - вы предполагаете, что код для входа в систему неизвестен злоумышленнику? В противном случае - не будет ли злоумышленник всегда знать соль, случайную, уникальную, хранящуюся вместе с хешированным паролем или отдельно?
mattstuehler
13

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

Ной Гудрич
источник
1
SHA-1 не подходит для хеширования паролей.
Жиль "ТАК - перестань быть злым"
10

Всегда используйте алгоритм хеширования пароля: Argon2 , scrypt , bcrypt или PBKDF2 .

Argon2 выиграл конкурс хэширования паролей в 2015 году. Scrypt , bcrypt и PBKDF2 - более старые алгоритмы, которые в настоящее время считаются менее предпочтительными, но все же являются фундаментально надежными, поэтому, если ваша платформа еще не поддерживает Argon2, сейчас можно использовать другой алгоритм.

Никогда не храните пароль непосредственно в базе данных. Также не шифруйте его: в противном случае, если ваш сайт будет взломан, злоумышленник получит ключ дешифрования и сможет получить все пароли. Пароли ДОЛЖНЫ быть хешированы .

Хэш пароля имеет различные свойства из хеш - таблицы хэш или криптографической хэш. Никогда не используйте обычный криптографический хеш, такой как MD5, SHA-256 или SHA-512 для пароля. Алгоритм хеширования паролей использует соль , которая является уникальной (не используется ни для какого другого пользователя или в чьей-либо другой базе данных). Соль необходима для того, чтобы злоумышленники не могли просто предварительно рассчитать хэши общих паролей: с солью они должны перезапустить расчет для каждой учетной записи. Алгоритм хеширования паролей по сути медленный - настолько медленный, насколько вы можете себе позволить. Медлительность причиняет злоумышленнику гораздо больше вреда, чем вам, потому что злоумышленнику приходится использовать много разных паролей. Для получения дополнительной информации см. Как безопасно хэшировать пароли .

Хэш пароля кодирует четыре фрагмента информации:

  • Индикатор того, какой алгоритм используется. Это необходимо для ловкости : криптографические рекомендации меняются со временем. Вы должны быть в состоянии перейти на новый алгоритм.
  • Индикатор сложности или твердости. Чем выше это значение, тем больше вычислений требуется для вычисления хэша. Это должно быть постоянное или глобальное значение конфигурации в функции смены пароля, но оно должно увеличиваться со временем, поскольку компьютеры работают быстрее, поэтому вам нужно запомнить значение для каждой учетной записи. Некоторые алгоритмы имеют одно числовое значение, другие имеют больше параметров (например, для индивидуальной настройки использования ЦП и ОЗУ).
  • Соль. Поскольку соль должна быть уникальной во всем мире, она должна храниться для каждой учетной записи. Соль должна генерироваться случайным образом при каждой смене пароля.
  • Собственно хеш, то есть вывод математического вычисления в алгоритм хеширования.

Многие библиотеки включают в себя пару функций, которые удобно упаковывают эту информацию в одну строку: одну, которая берет индикатор алгоритма, индикатор твердости и пароль, генерирует случайную соль и возвращает полную строку хеша; и тот, который принимает пароль и полную строку хеша в качестве входных данных и возвращает логическое значение, указывающее, был ли пароль правильным. Там нет универсального стандарта, но общая кодировка

$ алгоритм $ параметры $ соль $ вывод

где algorithmэто число или короткая буквенно - цифровая строка , кодирующий выбор алгоритма, parametersявляется печатной строкой, а saltи outputкодируются в Base64 без прекращения =.

16 байт достаточно для соли и вывода. (См., Например, рекомендации для Argon2 .) Кодированный в Base64, это 21 символ каждый. Две другие части зависят от алгоритма и параметров, но обычно используются 20–40 символов. Это в общей сложности около 82 символов ASCII ( CHAR(82)и не требует Unicode), к которым вы должны добавить запас прочности, если вы думаете, что будет трудно расширить поле позже.

Если вы закодируете хеш в двоичном формате, вы можете уменьшить его до 1 байта для алгоритма, от 1 до 4 байтов для твердости (если вы жестко кодируете некоторые параметры) и до 16 байтов для соли и выходных данных. , в общей сложности 37 байтов. Скажите 40 байтов ( BINARY(40)), чтобы иметь хотя бы пару свободных байтов. Обратите внимание, что это 8-битные байты, а не печатные символы, в частности, поле может содержать нулевые байты.

Обратите внимание, что длина хеша совершенно не связана с длиной пароля.

Жиль "ТАК - перестань быть злым"
источник
9

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

Дана вменяемая
источник
2
Это действительно очень полезно (+1), но это не отвечает на вопрос! (-1)
Билл Карвин
3
Да, но определенно актуально в этом контексте (+1)
Треб
7

В виде строки фиксированной длины (VARCHAR (n) или как MySQL ее называет). Хеш всегда имеет фиксированную длину, например, 12 символов (в зависимости от используемого вами алгоритма хеширования). Таким образом, пароль из 20 символов будет уменьшен до хеша из 12 символов, а пароль из 4 символов также даст хэш из 12 символов.

треб
источник
3
«или как MySQL называет это» - MYSQL называет это CHAR. Этот тип предназначен для фиксированной длины. Поэтому я думаю, что CHAR лучше, чем VARCHAR.
t298712383
4

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

Барт
источник
3

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

willasaywhat
источник
3

Хэши - это последовательность битов (128 бит, 160 бит, 256 бит и т. Д., В зависимости от алгоритма). Ваш столбец должен быть двоичным, а не текстовым / символьным, если MySQL это позволяет (тип данных SQL Server - binary(n)или varbinary(n)). Вы должны также посолить хэш. Соли могут быть текстовыми или двоичными, и вам понадобится соответствующий столбец.

yfeldblum
источник
Справедливость здесь совершенно верна - MySQL будет хранить их в виде числовых значений и сделает поиск по этому столбцу намного более эффективным, чем сопоставление строк, однако соли не должны храниться в базе данных, кроме соленых данных, что исключает безопасность, которую обеспечивают соли ,
Тони Маро
6
Соли не секрет. Только секрет , является пароль. Просто убедитесь, что каждый новый пароль получает новую соль. Каждый раз, когда пользователь меняет свой пароль, система должна генерировать новую соль для этого пароля. Соли должны быть длинными и случайными, например, 16 байтов, сгенерированных из криптографически безопасного PRNG.
yfeldblum
1
@TonyMaro Не уверен, что соответствие строки пароля на уровне SQL является хорошей стратегией. Другими словами, вам не следует искать в вашей базе данных пароль, вместо этого извлекать пользователя на основе его имени пользователя и сравнивать пароли в коде, а не в SQL.
Барта
1

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

Стивен Уолчер
источник
0

для md5 vARCHAR (32) подходит. Для тех, кто использует AES, лучше использовать varbinary.

Заяц Шриниваса
источник
1
Ни MD5, ни AES не подходят для хеширования пароля.
Жиль "ТАК - перестань быть злым"