Генерация соли в PHP


Каков наилучший способ сгенерировать криптографически защищенную 32-байтовую соль в PHP, не зависящую от библиотек, редко включенных в типичные установки PHP?

После некоторого поиска в Google я обнаружил, что mt_rand считается недостаточно безопасным, но я не нашел предложения по замене. В одной статье предлагалось читать из /dev/random, но это не только не будет работать в Windows; это также очень медленно.

Я хочу разумного баланса между безопасностью и скоростью (т. Е., для генерации 512 байт не должно потребоваться 20 секунд, как обычно делает /dev/random)

Author: qster, 2010-03-25

7 answers

Примечание: mcrypt устарел в PHP 7.1. Перейдите к обновленному ответу.

Возможно, вы захотите ознакомиться с документацией (и комментариями) для mcrypt_create_iv().

 7
Author: Amber, 2017-05-23 12:31:56

В PHP 7 это проще: Просто используйте $salt = random_bytes($numberOfDesiredBytes); для получения соли.

Для чего тебе вообще нужна соль? Если это для паролей, просто используйте password_hash() и password_verify().

 12
Author: Scott Arciszewski, 2015-12-09 07:42:02

Примечание: mcrypt устарел в PHP 7.1. Перейдите к обновленному ответу.

Вы можете использовать функцию mycrypt_create_iv(), поскольку PHP версии 5.3 также использует случайный источник на сервере Windows (не только в Unix). Перед его использованием вы должны проверить, определена ли константа MCRYPT_DEV_URANDOM.

mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);

В отличие от random, urandom не блокирует сервер, если доступной энтропии недостаточно. Поскольку соль пароля должна быть уникальной (не обязательно случайный), urandom кажется мне хорошим выбором.

 7
Author: martinstoeckli, 2017-05-23 11:46:12

uniqueid не очень хорошо подходит для генерации случайной строки, так как она тоже основана на microtime. Цикл процессора, как правило, намного короче, чем микротакт, что может привести к возможному постоянству для данной переменной в циклах. Установка второго параметра "энтропия" в значение true,

 uniqid('', true)

Обеспечит повышенную случайность.

Чтобы получить случайную строку, которая хорошо совместима с большинством наборов символов, можно применить кодировку base64 к инициализации mcrypt векторная функция mcrypt_create_iv:

$length = 16;
base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM))
//> hlZuRJypdHFQPtI2oSFrgA==
strlen(base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM)))
//> 16

Уменьшение алфавита символов до 2^6 бит увеличивает размер, который учитывался выше.

 2
Author: Lorenz Lo Sauer, 2013-09-19 15:57:48

Считывать из /dev/urandom или использовать openssl_random_pseudo_bytes().

 0
Author: D.W., 2012-08-03 16:48:57

Uniqid() должен подойти для этой цели.

 -3
Author: Crozin, 2010-03-25 08:04:48

Я думаю, что microtime() достаточно.

Странно, но я все еще получаю отрицательные отзывы за этот ответ.

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

 -9
Author: Your Common Sense, 2013-08-03 07:34:39