безопасность — веб-разработка / PHP: когда следует / не следует использовать криптографически безопасный токен?

Стандартный способ создания криптографически безопасного токена с использованием PHP выглядит следующим образом:

$token = bin2hex(openssl_random_pseudo_bytes(16));

Я понимаю, что если вы используете Linux (что я всегда делаю), потому что он использует / dev / urandom — который изменяется в соответствии со всеми многими вещами, происходящими в операционной системе, — это делает почти невозможным прогнозирование.

Моя функция больше похожа на эту, поэтому я могу сделать это по длине символа, а не по длине в битах (хотя я на самом деле никогда не использую это, см. Ниже):

function token($charLength = 32) {

// Each byte produces 2 hexadecimal characters so bit length should be half the char length
$bitLength = $charLength / 2;

// Generate token
$token = bin2hex(openssl_random_pseudo_bytes($bitLength));

return $token;

}

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

Вот почему, когда люди ссылаются на токены, они ссылаются на длину в битах, а не на длину символа?

Рассмотрим вместо этого:

function randomString($length,
$alpha = true,
$alphau = true,
$numeric = true,
$specialChars = '') {

$string = $specialChars;

if($alpha === true) {

$string .= 'abcdefghijklmnopqrstuvwxyz';

}

if($alphau === true) {

$string .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

}

if($numeric === true) {

$string .= '0123456789';

}

$array      = str_split($string);
$string     = '';

for($counter = 0; $counter < $length; $counter ++) {

$string .= $array[array_rand($array)];

}

return $string;

}

В контексте веб-разработки, когда бы вы использовали первую функцию над второй для:

  1. Создание случайного пароля для сброса пароля
  2. Создание токена одноразового использования (например, для ссылки на забытый пароль)
  3. Создание соли для хэша пароля (например, bcrypt, sha512, PBKDF2)
  4. Создание токена для токена cookie «запомнить меня»

Во всех случаях я использовал бы randomString (), а не token (), поэтому, я полагаю, я спрашиваю, не ошибаюсь ли я в чем-либо из вышеперечисленного.

Мое обоснование в отношении вышеуказанных пунктов:

  1. Трудно угадать 12-значный случайный пароль с прописными, строчными буквами и цифрами; плюс я замораживаю людей на 15 минут после 5 неудачных попыток входа
  2. 64-символьная случайная строка, если кто-то попытается перебросить токен методом перебора, то брандмауэр подберет его
  3. В любом случае следует считать, что соли являются общедоступными, поскольку они отличаются по паролю, что делает невозможным создание радужной таблицы.
  4. Мой токен «Помни меня» — это случайная строка длиной 128 символов, хранящаяся в cookie-файле, с солью и 512-й точкой в ​​базе данных.

0

Решение

Основной задачей генераторов случайных чисел, как правило, является не созданный вывод, а предсказуемость, в которой генерируются эти данные. Ваш основной вопрос: почему бы не использовать array_rand (который внутренне использует php_rand) поверх openssl_random_pseudo_bytes для криптографических целей. Ответ связан с техникой, которую использует каждая функция, а array_rand — гораздо более предсказуемый (и воспроизводимый) подход. См. Статью Падрайка Брэди «Предсказание случайных чисел в PHP — это проще, чем вы думаете!» для более подробной информации: http://blog.astrumfutura.com/2013/03/predicting-random-numbers-in-php-its-easier-than-you-think/.

Что касается выходных сигналов генераторов случайных чисел, то надежность пароля / ключа в отношении атак методом перебора часто измеряется энтропией. Обычно это указывается в битах, чем больше бит, тем лучше. Страница Википедии о надежности пароля (http://en.wikipedia.org/wiki/Password_strength) имеет несколько великолепных справочных таблиц для определения уровня энтропии паролей различной длины и использования различных комбинаций типов символов. Функция openssl_random_pseudo_bytes () использует все двоичные / шестнадцатеричные значения, что приводит к полному 8 битам энтропии на символ. В лучшем случае ваша функция randomString () будет давать 5,954 бита энтропии на символ.

введите описание изображения здесь

Использование крипто-сильного случайного числа следует использовать во всех сценариях, связанных с безопасностью, где возможность угадать одно из этих чисел может каким-то образом негативно повлиять на ваш сайт. Единственный элемент в вашем списке из 4, где я вижу, что не требуется крипто-сильное случайное число, это солт-значения для хэшей. Соленость должна быть универсально уникальной. Он, безусловно, может быть получен с помощью криптографического генератора случайных чисел (CRNG), но это не требуется, поскольку полученное значение может быть обнародовано. Увидеть https://security.stackexchange.com/questions/8246/what-is-a-good-enough-salt-for-a-saltedhash

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]