Чтобы сгенерировать 32-символьный токен для доступа к нашему API, мы в настоящее время используем:
$token = md5(uniqid(mt_rand(), true));
Я читал, что этот метод не является криптографически безопасным, поскольку он основан на системных часах, и это openssl_random_pseudo_bytes
было бы лучшим решением, поскольку его было бы труднее предсказать.
Если это так, как бы выглядел эквивалентный код?
Я предполагаю что-то подобное, но не знаю, правильно ли это ...
$token = md5(openssl_random_pseudo_bytes(32));
И какая длина имеет смысл передать функции?
md5()
генерирует строку из 32 символов, но содержит только 128 бит данных.openssl_random_pseudo_bytes()
возвращает истинные двоичные данные, поэтому имеет 32 * 8 = 256 битов случайности. Заполняя 32-байтовую случайную строку через md5, вы существенно сокращаете ее уникальность.$token = bin2hex(openssl_random_pseudo_bytes(16));
достаточно, или мне нужен цикл из 16 итераций, передающий 1 в качестве длины и добавляемый в шестнадцатеричном формате к строке?Random::alphanumericString($length)
, что позволяет уместить эти 16 символов примерно в 2 миллиарда раз больше «энтропии».Ответы:
Вот правильное решение:
$token = bin2hex(openssl_random_pseudo_bytes(16)); # or in php7 $token = bin2hex(random_bytes(16));
источник
bin2hex(random_bytes($length/2))
потому что у вас может быть 2 шестнадцатеричных символа для каждого байта, поэтому количество символов всегда будет удваиваться$length
без него$length
числа символов (а не заботится о размере байта), вы захотите передатьrandom_bytes($length/2)
.Если вы хотите использовать openssl_random_pseudo_bytes, лучше всего использовать реализацию CrytoLib, это позволит вам сгенерировать все буквенно-цифровые символы, прикрепление bin2hex вокруг openssl_random_pseudo_bytes просто приведет к тому, что вы получите AF (заглавные буквы) и числа.
Замените path / to / тем местом, где вы поместили файл cryptolib.php (вы можете найти его на GitHub по адресу: https://github.com/IcyApril/CryptoLib )
<?php require_once('path/to/cryptolib.php'); $token = IcyApril\CryptoLib::randomString(16); ?>
Полная документация CryptoLib доступна по адресу: https://cryptolib.ju.je/ . Он охватывает множество других случайных методов, каскадное шифрование, генерацию и проверку хэшей; но он есть, если вам это нужно.
источник
openssl_random_pseudo_bytes(16)
каждый байт может иметь любое значение (0-255), тогда какrandomString(16)
каждый байт может иметь только az Az 0-9, что составляет 62 комбинации на байт. Да, randomString лучше для длины строки , так как bin2hex неэффективное кодирование (50%); лучше использоватьbase64_encode(openssl_random_pseudo_bytes(16))
для более короткой строки и точного известного количества байтов безопасности (в данном случае 16, но при необходимости+
,/
и=
символы, так что если вы пытаетесь сформировать удобный маркер (например , ключ API) он не идеален.Если у вас есть криптографически безопасный генератор случайных чисел, вам не нужно хэшировать его вывод. На самом деле вы этого не хотите. Просто используйте
$token = openssl_random_pseudo_bytes($BYTES,true)
Где $ BYTES - сколько байтов данных вы хотите. MD5 имеет 128-битный хеш, поэтому достаточно 16 байт.
В качестве примечания: ни одна из функций, которые вы вызываете в исходном коде, не является криптографически безопасной, большинство из них достаточно опасны, поэтому использование только одной из них будет небезопасным, даже в сочетании с другими безопасными функциями. У MD5 есть проблемы с безопасностью (хотя для этого приложения они могут не иметь отношения). Uniqid не просто не генерирует криптографически случайные байты по умолчанию (поскольку он использует системные часы), добавленная энтропия, которую вы передаете, комбинируется с использованием линейного конгруэнтного генератора, что не является криптографически безопасным. Фактически, это, вероятно, означает, что можно было угадать все ваши ключи API, получив доступ к некоторым из них, даже если они не знали значение часов вашего сервера. Наконец, mt_rand (), то, что вы используете в качестве дополнительной энтропии, также не является безопасным генератором случайных чисел.
источник
Надежные пароли Вы можете составлять только из символов ascii a-zA-Z и цифр 0-9 . Для этого лучше всего использовать только криптографически безопасные методы, такие как random_int () или random_bytes () из PHP7. Остальные функции как base64_encode () Вы можете использовать только как вспомогательные функции, чтобы сделать строку надежной и изменить ее на символы ASCII .
mt_rand () небезопасен и очень старый. Из любой строки Вы должны использовать random_int (). Из двоичной строки Вы должны использовать base64_encode (), чтобы сделать двоичную строку надежной, или bin2hex, но тогда Вы сократите байт только до 16 позиций (значений). См. Мою реализацию этой функции. Он использует все языки.
источник